5 #include <mono/metadata/metadata.h>
6 #include <mono/metadata/tabledefs.h>
7 #include <mono/metadata/rawbuffer.h>
8 #include <mono/metadata/tokentype.h>
9 #include <mono/metadata/appdomain.h>
10 #include <mono/metadata/exception.h>
11 #include <mono/metadata/debug-helpers.h>
12 #include <mono/metadata/debug-mono-symfile.h>
17 #define RANGE_TABLE_CHUNK_SIZE 256
18 #define TYPE_TABLE_CHUNK_SIZE 256
20 struct MonoSymbolFilePriv
27 guint32 string_table_size;
28 guint32 string_offset_size;
30 GHashTable *method_table;
31 GHashTable *method_hash;
32 MonoSymbolFileOffsetTable *offset_table;
38 MonoDebugMethodInfo *minfo;
39 MonoSymbolFileMethodEntry *entry;
40 guint32 method_name_offset;
43 } MonoSymbolFileMethodEntryPriv;
45 static GHashTable *type_table;
46 static GHashTable *class_table;
48 static int write_string_table (MonoSymbolFile *symfile);
49 static int create_symfile (MonoSymbolFile *symfile, gboolean emit_warnings);
50 static void close_symfile (MonoSymbolFile *symfile);
51 static MonoDebugRangeInfo *allocate_range_entry (MonoSymbolFile *symfile);
52 static MonoDebugTypeInfo *allocate_type_entry (MonoSymbolFile *symfile);
53 static gpointer write_type (MonoType *type);
56 free_method_info (MonoDebugMethodInfo *minfo)
63 get_class_name (MonoClass *klass)
65 if (klass->nested_in) {
66 gchar *parent_name = get_class_name (klass->nested_in);
67 gchar *name = g_strdup_printf ("%s.%s", parent_name, klass->name);
72 return g_strdup_printf ("%s%s%s", klass->name_space,
73 klass->name_space [0] ? "." : "", klass->name);
77 get_method_name (MonoMethod *method)
79 gchar *tmpsig = mono_signature_get_desc (method->signature, TRUE);
80 gchar *class_name = get_class_name (method->klass);
81 gchar *name = g_strdup_printf ("%s.%s(%s)", class_name, method->name, tmpsig);
88 load_symfile (MonoSymbolFile *symfile)
90 MonoSymbolFilePriv *priv = symfile->_priv;
91 MonoSymbolFileMethodEntry *me;
92 const char *ptr, *start;
97 ptr = start = symfile->raw_contents;
99 magic = *((guint64 *) ptr)++;
100 if (magic != MONO_SYMBOL_FILE_MAGIC) {
101 g_warning ("Symbol file %s has is not a mono symbol file", priv->file_name);
105 version = *((guint32 *) ptr)++;
106 if (version != MONO_SYMBOL_FILE_VERSION) {
107 g_warning ("Symbol file %s has incorrect line number table version "
108 "(expected %d, got %ld)", priv->file_name,
109 MONO_SYMBOL_FILE_VERSION, version);
113 priv->offset_table = (MonoSymbolFileOffsetTable *) ptr;
115 mono_debug_symfile_add_type (symfile, mono_defaults.object_class);
122 priv->method_table = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
123 (GDestroyNotify) g_free);
124 priv->method_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
125 (GDestroyNotify) free_method_info);
127 ptr = symfile->raw_contents + priv->offset_table->method_table_offset;
128 me = (MonoSymbolFileMethodEntry *) ptr;
130 for (i = 0; i < priv->offset_table->method_count; i++, me++) {
131 MonoMethod *method = mono_get_method (priv->image, me->token, NULL);
132 MonoSymbolFileMethodEntryPriv *mep;
133 MonoDebugMethodInfo *minfo;
138 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
139 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
140 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
141 (method->flags & METHOD_ATTRIBUTE_ABSTRACT))
142 g_assert_not_reached ();
144 if (!((MonoMethodNormal *) method)->header) {
145 g_warning (G_STRLOC ": Internal error: method %s.%s doesn't have a header",
146 method->klass->name, method->name);
150 minfo = g_new0 (MonoDebugMethodInfo, 1);
151 minfo->file_offset = ((const char *) me) - start;
152 minfo->method = method;
153 minfo->symfile = symfile;
154 minfo->num_il_offsets = me->num_line_numbers;
155 minfo->il_offsets = (MonoSymbolFileLineNumberEntry *)
156 (symfile->raw_contents + me->line_number_table_offset);
158 mep = g_new0 (MonoSymbolFileMethodEntryPriv, 1);
159 mep->method = method;
164 mep->method_name_offset = priv->string_table_size;
165 mep->name = get_method_name (method);
166 priv->string_table_size += strlen (mep->name) + 5;
168 g_hash_table_insert (priv->method_table, method, mep);
169 g_hash_table_insert (priv->method_hash, method, minfo);
172 if (!write_string_table (symfile))
179 mono_debug_open_mono_symbol_file (MonoImage *image, const char *filename, gboolean emit_warnings)
181 MonoSymbolFile *symfile;
182 MonoSymbolFilePriv *priv;
187 fd = open (filename, O_RDONLY);
190 g_warning ("Can't open symbol file: %s", filename);
194 file_size = lseek (fd, 0, SEEK_END);
195 lseek (fd, 0, SEEK_SET);
197 if (file_size == (off_t) -1) {
199 g_warning ("Can't get size of symbol file: %s", filename);
203 ptr = mono_raw_buffer_load (fd, FALSE, 0, file_size);
206 g_warning ("Can't read symbol file: %s", filename);
210 symfile = g_new0 (MonoSymbolFile, 1);
211 symfile->magic = MONO_SYMBOL_FILE_MAGIC;
212 symfile->version = MONO_SYMBOL_FILE_VERSION;
213 symfile->dynamic_magic = MONO_SYMBOL_FILE_DYNAMIC_MAGIC;
214 symfile->dynamic_version = MONO_SYMBOL_FILE_DYNAMIC_VERSION;
215 symfile->image_file = g_strdup (image->name);
216 symfile->symbol_file = g_strdup (filename);
217 symfile->raw_contents = ptr;
218 symfile->raw_contents_size = file_size;
220 symfile->_priv = priv = g_new0 (MonoSymbolFilePriv, 1);
224 priv->file_name = g_strdup (filename);
226 if (!load_symfile (symfile)) {
227 mono_debug_close_mono_symbol_file (symfile);
235 close_symfile (MonoSymbolFile *symfile)
237 MonoSymbolFilePriv *priv = symfile->_priv;
239 if (symfile->raw_contents) {
240 mono_raw_buffer_free (symfile->raw_contents);
241 symfile->raw_contents = NULL;
249 if (priv->method_table) {
250 g_hash_table_destroy (priv->method_table);
251 priv->method_table = NULL;
254 if (symfile->is_dynamic) {
255 unlink (priv->file_name);
256 priv->method_hash = NULL;
257 } else if (priv->method_hash) {
258 g_hash_table_destroy (priv->method_hash);
259 priv->method_hash = NULL;
262 if (symfile->image_file) {
263 g_free (symfile->image_file);
264 symfile->image_file = NULL;
267 if (priv->file_name) {
268 g_free (priv->file_name);
269 priv->file_name = NULL;
276 mono_debug_close_mono_symbol_file (MonoSymbolFile *symfile)
281 close_symfile (symfile);
283 g_free (symfile->_priv->source_file);
284 g_free (symfile->_priv);
285 g_free (symfile->image_file);
286 g_free (symfile->symbol_file);
291 read_string (const char *ptr)
293 int len = *((guint32 *) ptr)++;
295 return g_filename_from_utf8 (ptr, len, NULL, NULL, NULL);
299 mono_debug_find_source_location (MonoSymbolFile *symfile, MonoMethod *method, guint32 offset,
300 guint32 *line_number)
302 MonoSymbolFilePriv *priv = symfile->_priv;
303 MonoSymbolFileLineNumberEntry *lne;
304 MonoSymbolFileMethodEntryPriv *mep;
305 gchar *source_file = NULL;
309 if (!priv->method_table || symfile->is_dynamic)
312 mep = g_hash_table_lookup (priv->method_table, method);
316 if (mep->entry->source_file_offset)
317 source_file = read_string (symfile->raw_contents + mep->entry->source_file_offset);
319 ptr = symfile->raw_contents + mep->entry->line_number_table_offset;
321 lne = (MonoSymbolFileLineNumberEntry *) ptr;
323 for (i = 0; i < mep->entry->num_line_numbers; i++, lne++) {
324 if (lne->offset < offset)
328 *line_number = lne->row;
333 } else if (source_file) {
334 gchar *retval = g_strdup_printf ("%s:%d", source_file, lne->row);
335 g_free (source_file);
338 return g_strdup_printf ("%d", lne->row);
345 mono_debug_symfile_add_method (MonoSymbolFile *symfile, MonoMethod *method)
347 MonoSymbolFileMethodEntryPriv *mep;
348 MonoSymbolFileMethodAddress *address;
349 MonoDebugVarInfo *var_table;
350 MonoDebugRangeInfo *range;
351 guint32 size, num_variables, variable_size, variable_offset;
352 guint32 type_size, type_offset, *type_index_table;
353 gpointer *type_table;
357 if (!symfile->_priv->method_table)
360 mep = g_hash_table_lookup (symfile->_priv->method_table, method);
365 mep->minfo = g_hash_table_lookup (symfile->_priv->method_hash, mep->method);
370 if (!mep->minfo->jit)
373 symfile->generation++;
375 size = sizeof (MonoSymbolFileMethodAddress);
377 num_variables = mep->entry->num_parameters + mep->entry->num_locals;
378 if (mep->entry->this_type_index)
381 variable_size = num_variables * sizeof (MonoDebugVarInfo);
382 variable_offset = size;
383 size += variable_size;
385 type_size = num_variables * sizeof (gpointer);
389 address = g_malloc0 (size);
390 ptr = (guint8 *) address;
392 address->size = size;
393 address->start_address = mep->minfo->jit->code_start;
394 address->end_address = mep->minfo->jit->code_start + mep->minfo->jit->code_size;
395 address->method_start_address = address->start_address + mep->minfo->jit->prologue_end;
396 address->method_end_address = address->start_address + mep->minfo->jit->epilogue_begin;
397 address->variable_table_offset = variable_offset;
398 address->type_table_offset = type_offset;
400 if (mep->minfo->jit->line_numbers) {
401 address->num_line_numbers = mep->minfo->jit->line_numbers->len;
402 address->line_numbers = (MonoDebugLineNumberEntry *) mep->minfo->jit->line_numbers->data;
403 address->line_number_size = address->num_line_numbers * sizeof (MonoDebugLineNumberEntry);
406 range = allocate_range_entry (symfile);
407 range->file_offset = mep->minfo->file_offset;
408 range->start_address = address->start_address;
409 range->end_address = address->end_address;
410 range->dynamic_data = address;
411 range->dynamic_size = size;
413 var_table = (MonoDebugVarInfo *) (ptr + variable_offset);
414 type_table = (gpointer *) (ptr + type_offset);
416 type_index_table = (guint32 *)
417 (symfile->raw_contents + mep->entry->type_index_table_offset);
419 if (mep->entry->this_type_index) {
420 if (!mep->minfo->jit->this_var) {
421 g_warning (G_STRLOC ": Method %s.%s doesn't have `this'.",
422 mep->method->klass->name, mep->method->name);
425 *var_table++ = *mep->minfo->jit->this_var;
426 *type_table++ = write_type (&method->klass->this_arg);
430 if (mep->minfo->jit->num_params != mep->entry->num_parameters) {
431 g_warning (G_STRLOC ": Method %s.%s has %d parameters, but symbol file claims it has %d.",
432 mep->method->klass->name, mep->method->name, mep->minfo->jit->num_params,
433 mep->entry->num_parameters);
435 var_table += mep->entry->num_parameters;
437 for (i = 0; i < mep->minfo->jit->num_params; i++) {
438 *var_table++ = mep->minfo->jit->params [i];
439 *type_table++ = write_type (method->signature->params [i]);
443 if (mep->minfo->jit->num_locals != mep->entry->num_locals) {
445 g_warning (G_STRLOC ": Method %s.%s has %d locals, but symbol file claims it has %d.",
446 mep->method->klass->name, mep->method->name, mep->minfo->jit->num_locals,
447 mep->entry->num_locals);
449 var_table += mep->entry->num_locals;
451 for (i = 0; i < mep->minfo->jit->num_locals; i++)
452 *var_table++ = mep->minfo->jit->locals [i];
456 mono_debug_symfile_add_type (MonoSymbolFile *symfile, MonoClass *klass)
458 MonoDebugTypeInfo *info;
461 class_table = g_hash_table_new (g_direct_hash, g_direct_equal);
463 /* We write typeof (object) into each symbol file's type table. */
464 if ((klass != mono_defaults.object_class) && g_hash_table_lookup (class_table, klass))
467 symfile->generation++;
469 info = allocate_type_entry (symfile);
472 info->token = klass->element_class->type_token;
473 info->rank = klass->rank;
475 info->token = klass->type_token;
476 info->type_info = write_type (&klass->this_arg);
480 create_symfile (MonoSymbolFile *symfile, gboolean emit_warnings)
482 MonoSymbolFilePriv *priv = symfile->_priv;
488 priv->fd = g_file_open_tmp (NULL, &priv->file_name, NULL);
489 if (priv->fd == -1) {
491 g_warning ("Can't create symbol file");
495 symfile->symbol_file = g_strdup (priv->file_name);
497 magic = MONO_SYMBOL_FILE_MAGIC;
498 if (write (priv->fd, &magic, sizeof (magic)) < 0)
501 version = MONO_SYMBOL_FILE_VERSION;
502 if (write (priv->fd, &version, sizeof (version)) < 0)
505 offset = lseek (priv->fd, 0, SEEK_CUR);
507 priv->offset_table = g_new0 (MonoSymbolFileOffsetTable, 1);
508 if (write (priv->fd, priv->offset_table, sizeof (MonoSymbolFileOffsetTable)) < 0)
511 mono_debug_symfile_add_type (symfile, mono_defaults.object_class);
514 // Write offset table.
517 symfile->raw_contents_size = lseek (priv->fd, 0, SEEK_CUR);
519 lseek (priv->fd, offset, SEEK_SET);
520 if (write (priv->fd, priv->offset_table, sizeof (MonoSymbolFileOffsetTable)) < 0)
523 lseek (priv->fd, symfile->raw_contents_size, SEEK_SET);
525 ptr = mono_raw_buffer_load (priv->fd, TRUE, 0, symfile->raw_contents_size);
529 symfile->raw_contents = ptr;
535 mono_debug_create_mono_symbol_file (MonoImage *image)
537 MonoSymbolFile *symfile;
539 symfile = g_new0 (MonoSymbolFile, 1);
540 symfile->magic = MONO_SYMBOL_FILE_MAGIC;
541 symfile->version = MONO_SYMBOL_FILE_VERSION;
542 symfile->dynamic_magic = MONO_SYMBOL_FILE_DYNAMIC_MAGIC;
543 symfile->dynamic_version = MONO_SYMBOL_FILE_DYNAMIC_VERSION;
544 symfile->is_dynamic = TRUE;
545 symfile->image_file = g_strdup (image->name);
547 symfile->_priv = g_new0 (MonoSymbolFilePriv, 1);
548 symfile->_priv->image = image;
550 if (!create_symfile (symfile, TRUE)) {
551 mono_debug_close_mono_symbol_file (symfile);
558 MonoDebugMethodInfo *
559 mono_debug_find_method (MonoSymbolFile *symfile, MonoMethod *method)
561 if (!symfile->_priv->method_hash)
564 return g_hash_table_lookup (symfile->_priv->method_hash, method);
568 write_method_name (gpointer key, gpointer value, gpointer user_data)
570 MonoSymbolFile *symfile = (MonoSymbolFile *) user_data;
571 MonoSymbolFileMethodEntryPriv *mep = (MonoSymbolFileMethodEntryPriv *) value;
572 MonoSymbolFilePriv *priv = symfile->_priv;
573 guint8 *offset_ptr, *string_ptr;
576 offset = mep->method_name_offset + priv->string_offset_size;
578 offset_ptr = symfile->string_table + mep->index * 4;
579 string_ptr = symfile->string_table + offset;
581 *((guint32 *) offset_ptr) = offset;
582 *((guint32 *) string_ptr)++ = strlen (mep->name);
583 strcpy (string_ptr, mep->name);
587 write_string_table (MonoSymbolFile *symfile)
589 MonoSymbolFilePriv *priv = symfile->_priv;
591 priv->string_offset_size = priv->offset_table->method_count * 4;
593 symfile->string_table_size = priv->string_table_size + priv->string_offset_size;
594 symfile->string_table = g_malloc0 (symfile->string_table_size);
596 g_hash_table_foreach (symfile->_priv->method_table, write_method_name, symfile);
600 MonoReflectionMethod *
601 ves_icall_MonoDebugger_GetMethod (MonoReflectionAssembly *assembly, guint32 token)
605 method = mono_get_method (assembly->assembly->image, token, NULL);
607 return mono_method_get_object (mono_domain_get (), method, NULL);
611 ves_icall_MonoDebugger_GetType (MonoReflectionAssembly *assembly, guint32 token)
615 klass = mono_class_get (assembly->assembly->image, token);
617 g_warning (G_STRLOC ": %x", token);
621 return mono_type_get_object (mono_domain_get (), &klass->byval_arg);
625 ves_icall_MonoDebugger_GetLocalTypeFromSignature (MonoReflectionAssembly *assembly, MonoArray *signature)
633 MONO_CHECK_ARG_NULL (assembly);
634 MONO_CHECK_ARG_NULL (signature);
636 domain = mono_domain_get();
637 image = assembly->assembly->image;
639 ptr = mono_array_addr (signature, char, 0);
640 g_assert (*ptr++ == 0x07);
641 len = mono_metadata_decode_value (ptr, &ptr);
644 type = mono_metadata_parse_type (image, MONO_PARSE_LOCAL, 0, ptr, &ptr);
646 return mono_type_get_object (domain, type);
649 static MonoDebugRangeInfo *
650 allocate_range_entry (MonoSymbolFile *symfile)
652 MonoDebugRangeInfo *retval;
653 guint32 size, chunks;
655 symfile->range_entry_size = sizeof (MonoDebugRangeInfo);
657 if (!symfile->range_table) {
658 size = sizeof (MonoDebugRangeInfo) * RANGE_TABLE_CHUNK_SIZE;
659 symfile->range_table = g_malloc0 (size);
660 symfile->num_range_entries = 1;
661 return symfile->range_table;
664 if (!((symfile->num_range_entries + 1) % RANGE_TABLE_CHUNK_SIZE)) {
665 chunks = (symfile->num_range_entries + 1) / RANGE_TABLE_CHUNK_SIZE;
666 size = sizeof (MonoDebugRangeInfo) * RANGE_TABLE_CHUNK_SIZE * (chunks + 1);
668 symfile->range_table = g_realloc (symfile->range_table, size);
671 retval = symfile->range_table + symfile->num_range_entries;
672 symfile->num_range_entries++;
676 static MonoDebugTypeInfo *
677 allocate_type_entry (MonoSymbolFile *symfile)
679 MonoDebugTypeInfo *retval;
680 guint32 size, chunks;
682 symfile->type_entry_size = sizeof (MonoDebugTypeInfo);
684 if (!symfile->type_table) {
685 size = sizeof (MonoDebugTypeInfo) * TYPE_TABLE_CHUNK_SIZE;
686 symfile->type_table = g_malloc0 (size);
687 symfile->num_type_entries = 1;
688 return symfile->type_table;
691 if (!((symfile->num_type_entries + 1) % TYPE_TABLE_CHUNK_SIZE)) {
692 chunks = (symfile->num_type_entries + 1) / TYPE_TABLE_CHUNK_SIZE;
693 size = sizeof (MonoDebugTypeInfo) * TYPE_TABLE_CHUNK_SIZE * (chunks + 1);
695 symfile->type_table = g_realloc (symfile->type_table, size);
698 retval = symfile->type_table + symfile->num_type_entries;
699 symfile->num_type_entries++;
704 write_simple_type (MonoType *type)
706 guint8 buffer [BUFSIZ], *ptr = buffer, *retval;
710 type_table = g_hash_table_new (g_direct_hash, g_direct_equal);
712 retval = g_hash_table_lookup (type_table, type);
716 switch (type->type) {
717 case MONO_TYPE_BOOLEAN:
720 *((int *) ptr)++ = 1;
726 *((int *) ptr)++ = 2;
732 *((int *) ptr)++ = 4;
738 *((int *) ptr)++ = 8;
741 case MONO_TYPE_STRING: {
744 *((int *) ptr)++ = -8;
745 *((guint32 *) ptr)++ = sizeof (MonoString);
747 *ptr++ = (guint8*)&string.length - (guint8*)&string;
748 *ptr++ = sizeof (string.length);
749 *ptr++ = (guint8*)&string.chars - (guint8*)&string;
759 retval = g_malloc0 (size + 4);
760 memcpy (retval + 4, buffer, size);
761 *((int *) retval) = size;
763 g_hash_table_insert (type_table, type, retval);
769 write_type (MonoType *type)
771 guint8 buffer [BUFSIZ], *ptr = buffer, *retval;
772 GPtrArray *methods = NULL;
773 int num_fields = 0, num_properties = 0, num_methods = 0;
774 int num_params = 0, kind;
775 guint32 size, data_size;
779 type_table = g_hash_table_new (g_direct_hash, g_direct_equal);
781 class_table = g_hash_table_new (g_direct_hash, g_direct_equal);
783 retval = g_hash_table_lookup (type_table, type);
787 retval = write_simple_type (type);
792 if (kind == MONO_TYPE_OBJECT) {
793 klass = mono_defaults.object_class;
794 kind = MONO_TYPE_CLASS;
795 } else if ((kind == MONO_TYPE_VALUETYPE) || (kind == MONO_TYPE_CLASS)) {
796 klass = type->data.klass;
797 retval = g_hash_table_lookup (class_table, klass);
803 case MONO_TYPE_SZARRAY:
804 size = 8 + sizeof (int) + sizeof (gpointer);
807 case MONO_TYPE_ARRAY:
808 size = 15 + sizeof (int) + sizeof (gpointer);
811 case MONO_TYPE_VALUETYPE:
812 case MONO_TYPE_CLASS: {
813 GHashTable *method_slots = NULL;
816 if (klass->init_pending) {
821 mono_class_init (klass);
823 retval = g_hash_table_lookup (class_table, klass);
827 if (klass->enumtype) {
828 size = 5 + sizeof (int) + sizeof (gpointer);
832 for (i = 0; i < klass->field.count; i++)
833 if (!(klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
836 for (i = 0; i < klass->property.count; i++)
837 if (!(klass->properties [i].attrs & FIELD_ATTRIBUTE_STATIC))
840 method_slots = g_hash_table_new (NULL, NULL);
841 methods = g_ptr_array_new ();
843 for (i = klass->method.count - 1; i >= 0; i--) {
844 MonoMethod *method = klass->methods [i];
846 if (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)
848 if (method->flags & (METHOD_ATTRIBUTE_STATIC | METHOD_ATTRIBUTE_SPECIAL_NAME))
850 if (!((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))
852 if (g_hash_table_lookup (method_slots, GUINT_TO_POINTER (method->slot)))
854 g_hash_table_insert (method_slots, GUINT_TO_POINTER (method->slot), method);
857 num_params += method->signature->param_count;
859 g_ptr_array_add (methods, method);
862 g_hash_table_destroy (method_slots);
864 size = 30 + sizeof (int) + num_fields * (4 + sizeof (gpointer)) +
865 num_properties * 3 * sizeof (gpointer) + num_methods * (4 + 2 * sizeof (gpointer)) +
866 num_params * sizeof (gpointer);
868 if (kind == MONO_TYPE_CLASS)
869 size += sizeof (gpointer);
880 retval = g_malloc0 (data_size + 4);
881 memcpy (retval + 4, buffer, data_size);
882 *((int *) retval) = data_size;
884 g_hash_table_insert (type_table, type, retval);
889 case MONO_TYPE_SZARRAY: {
892 *((int *) ptr)++ = -size;
893 *((guint32 *) ptr)++ = sizeof (MonoArray);
895 *ptr++ = (guint8*)&array.max_length - (guint8*)&array;
896 *ptr++ = sizeof (array.max_length);
897 *ptr++ = (guint8*)&array.vector - (guint8*)&array;
898 *((gpointer *) ptr)++ = write_type (type->data.type);
902 case MONO_TYPE_ARRAY: {
904 MonoArrayBounds bounds;
906 *((int *) ptr)++ = -size;
907 *((guint32 *) ptr)++ = sizeof (MonoArray);
909 *ptr++ = (guint8*)&array.max_length - (guint8*)&array;
910 *ptr++ = sizeof (array.max_length);
911 *ptr++ = (guint8*)&array.vector - (guint8*)&array;
912 *ptr++ = type->data.array->rank;
913 *ptr++ = (guint8*)&array.bounds - (guint8*)&array;
914 *ptr++ = sizeof (MonoArrayBounds);
915 *ptr++ = (guint8*)&bounds.lower_bound - (guint8*)&bounds;
916 *ptr++ = sizeof (bounds.lower_bound);
917 *ptr++ = (guint8*)&bounds.length - (guint8*)&bounds;
918 *ptr++ = sizeof (bounds.length);
919 *((gpointer *) ptr)++ = write_type (type->data.array->type);
923 case MONO_TYPE_VALUETYPE:
924 case MONO_TYPE_CLASS: {
925 int base_offset = kind == MONO_TYPE_CLASS ? 0 : - sizeof (MonoObject);
928 if (klass->init_pending) {
929 *((int *) ptr)++ = -1;
933 g_hash_table_insert (class_table, klass, retval);
935 if (klass->enumtype) {
936 *((int *) ptr)++ = -size;
937 *((guint32 *) ptr)++ = sizeof (MonoObject);
939 *((gpointer *) ptr)++ = write_type (klass->enum_basetype);
943 *((int *) ptr)++ = -size;
945 *((guint32 *) ptr)++ = klass->instance_size + base_offset;
946 if (type->type == MONO_TYPE_OBJECT)
949 *ptr++ = kind == MONO_TYPE_CLASS ? 6 : 5;
950 *ptr++ = kind == MONO_TYPE_CLASS;
951 *((guint32 *) ptr)++ = num_fields;
952 *((guint32 *) ptr)++ = num_fields * (4 + sizeof (gpointer));
953 *((guint32 *) ptr)++ = num_properties;
954 *((guint32 *) ptr)++ = num_properties * 3 * sizeof (gpointer);
955 *((guint32 *) ptr)++ = num_methods;
956 *((guint32 *) ptr)++ = num_methods * (4 + 2 * sizeof (gpointer)) +
957 num_params * sizeof (gpointer);
958 for (i = 0; i < klass->field.count; i++) {
959 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
962 *((guint32 *) ptr)++ = klass->fields [i].offset + base_offset;
963 *((gpointer *) ptr)++ = write_type (klass->fields [i].type);
966 for (i = 0; i < klass->property.count; i++) {
967 if (klass->properties [i].attrs & FIELD_ATTRIBUTE_STATIC)
970 if (klass->properties [i].get)
971 *((gpointer *) ptr)++ = write_type (klass->properties [i].get->signature->ret);
973 *((gpointer *) ptr)++ = NULL;
974 *((gpointer *) ptr)++ = klass->properties [i].get;
975 *((gpointer *) ptr)++ = klass->properties [i].set;
978 for (i = 0; i < methods->len; i++) {
979 MonoMethod *method = g_ptr_array_index (methods, i);
981 *((gpointer *) ptr)++ = method;
982 if (method->signature->ret)
983 *((gpointer *) ptr)++ = write_type (method->signature->ret);
985 *((gpointer *) ptr)++ = NULL;
986 *((guint32 *) ptr)++ = method->signature->param_count;
987 for (j = 0; j < method->signature->param_count; j++)
988 *((gpointer *) ptr)++ = write_type (method->signature->params [j]);
991 g_ptr_array_free (methods, FALSE);
993 if (kind == MONO_TYPE_CLASS) {
995 *((gpointer *) ptr)++ = write_type (&klass->parent->this_arg);
997 *((gpointer *) ptr)++ = NULL;
1004 g_message (G_STRLOC ": %p - %x,%x,%x", type, type->attrs, kind, type->byref);
1006 *((int *) ptr)++ = -1;