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
26 guint32 string_table_size;
27 guint32 string_offset_size;
29 GHashTable *method_table;
30 GHashTable *method_hash;
31 MonoSymbolFileOffsetTable *offset_table;
37 MonoDebugMethodInfo *minfo;
38 MonoSymbolFileMethodEntry *entry;
39 guint32 method_name_offset;
42 } MonoSymbolFileMethodEntryPriv;
44 static GHashTable *type_table;
46 static int write_string_table (MonoSymbolFile *symfile);
47 static int create_symfile (MonoSymbolFile *symfile, gboolean emit_warnings);
48 static void close_symfile (MonoSymbolFile *symfile);
49 static MonoDebugRangeInfo *allocate_range_entry (MonoSymbolFile *symfile);
50 static MonoDebugTypeInfo *allocate_type_entry (MonoSymbolFile *symfile);
51 static gpointer write_type (MonoType *type);
54 free_method_info (MonoDebugMethodInfo *minfo)
61 load_symfile (MonoSymbolFile *symfile)
63 MonoSymbolFilePriv *priv = symfile->_priv;
64 MonoSymbolFileMethodEntry *me;
65 const char *ptr, *start;
70 ptr = start = symfile->raw_contents;
72 magic = *((guint64 *) ptr)++;
73 if (magic != MONO_SYMBOL_FILE_MAGIC) {
74 g_warning ("Symbol file %s has is not a mono symbol file", priv->file_name);
78 version = *((guint32 *) ptr)++;
79 if (version != MONO_SYMBOL_FILE_VERSION) {
80 g_warning ("Symbol file %s has incorrect line number table version "
81 "(expected %d, got %ld)", priv->file_name,
82 MONO_SYMBOL_FILE_VERSION, version);
86 priv->offset_table = (MonoSymbolFileOffsetTable *) ptr;
93 priv->method_table = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
94 (GDestroyNotify) g_free);
95 priv->method_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
96 (GDestroyNotify) free_method_info);
98 ptr = symfile->raw_contents + priv->offset_table->method_table_offset;
99 me = (MonoSymbolFileMethodEntry *) ptr;
101 for (i = 0; i < priv->offset_table->method_count; i++, me++) {
102 MonoMethod *method = mono_get_method (priv->image, me->token, NULL);
103 MonoSymbolFileMethodEntryPriv *mep;
104 MonoDebugMethodInfo *minfo;
109 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
110 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
111 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
112 g_assert_not_reached ();
114 if (!((MonoMethodNormal *) method)->header) {
115 g_warning (G_STRLOC ": Internal error: method %s.%s doesn't have a header",
116 method->klass->name, method->name);
120 minfo = g_new0 (MonoDebugMethodInfo, 1);
121 minfo->file_offset = ((const char *) me) - start;
122 minfo->method = method;
123 minfo->symfile = symfile;
124 minfo->num_il_offsets = me->num_line_numbers;
125 minfo->il_offsets = (MonoSymbolFileLineNumberEntry *)
126 (symfile->raw_contents + me->line_number_table_offset);
128 mep = g_new0 (MonoSymbolFileMethodEntryPriv, 1);
129 mep->method = method;
134 mep->method_name_offset = priv->string_table_size;
135 mep->name = g_strdup_printf ("%s%s.%s", method->klass->name_space,
136 method->klass->name, method->name);
137 priv->string_table_size += strlen (mep->name) + 1;
139 g_hash_table_insert (priv->method_table, method, mep);
140 g_hash_table_insert (priv->method_hash, method, minfo);
143 if (!write_string_table (symfile))
150 mono_debug_open_mono_symbol_file (MonoImage *image, const char *filename, gboolean emit_warnings)
152 MonoSymbolFile *symfile;
153 MonoSymbolFilePriv *priv;
158 fd = open (filename, O_RDONLY);
161 g_warning ("Can't open symbol file: %s", filename);
165 file_size = lseek (fd, 0, SEEK_END);
166 lseek (fd, 0, SEEK_SET);
168 if (file_size == (off_t) -1) {
170 g_warning ("Can't get size of symbol file: %s", filename);
174 ptr = mono_raw_buffer_load (fd, FALSE, 0, file_size);
177 g_warning ("Can't read symbol file: %s", filename);
181 symfile = g_new0 (MonoSymbolFile, 1);
182 symfile->magic = MONO_SYMBOL_FILE_MAGIC;
183 symfile->version = MONO_SYMBOL_FILE_VERSION;
184 symfile->dynamic_magic = MONO_SYMBOL_FILE_DYNAMIC_MAGIC;
185 symfile->dynamic_version = MONO_SYMBOL_FILE_DYNAMIC_VERSION;
186 symfile->image_file = g_strdup (image->name);
187 symfile->symbol_file = g_strdup (filename);
188 symfile->raw_contents = ptr;
189 symfile->raw_contents_size = file_size;
191 symfile->_priv = priv = g_new0 (MonoSymbolFilePriv, 1);
195 priv->file_name = g_strdup (filename);
197 if (!load_symfile (symfile)) {
198 mono_debug_close_mono_symbol_file (symfile);
206 close_symfile (MonoSymbolFile *symfile)
208 MonoSymbolFilePriv *priv = symfile->_priv;
210 if (symfile->raw_contents) {
211 mono_raw_buffer_free (symfile->raw_contents);
212 symfile->raw_contents = NULL;
220 if (priv->method_table) {
221 g_hash_table_destroy (priv->method_table);
222 priv->method_table = NULL;
225 if (symfile->is_dynamic) {
226 unlink (priv->file_name);
227 priv->method_hash = NULL;
228 } else if (priv->method_hash) {
229 g_hash_table_destroy (priv->method_hash);
230 priv->method_hash = NULL;
233 if (symfile->image_file) {
234 g_free (symfile->image_file);
235 symfile->image_file = NULL;
238 if (priv->file_name) {
239 g_free (priv->file_name);
240 priv->file_name = NULL;
247 mono_debug_close_mono_symbol_file (MonoSymbolFile *symfile)
252 close_symfile (symfile);
254 g_free (symfile->_priv->source_file);
255 g_free (symfile->_priv);
256 g_free (symfile->image_file);
257 g_free (symfile->symbol_file);
262 write_string (int fd, const char *string)
264 guint32 length = strlen (string);
266 if (write (fd, &length, sizeof (length)) < 0)
269 if (write (fd, string, strlen (string)) < 0)
276 read_string (const char *ptr)
278 int len = *((guint32 *) ptr)++;
280 return g_filename_from_utf8 (ptr, len, NULL, NULL, NULL);
284 mono_debug_find_source_location (MonoSymbolFile *symfile, MonoMethod *method, guint32 offset,
285 guint32 *line_number)
287 MonoSymbolFilePriv *priv = symfile->_priv;
288 MonoSymbolFileLineNumberEntry *lne;
289 MonoSymbolFileMethodEntryPriv *mep;
290 gchar *source_file = NULL;
294 if (!priv->method_table || symfile->is_dynamic)
297 mep = g_hash_table_lookup (priv->method_table, method);
301 if (mep->entry->source_file_offset)
302 source_file = read_string (symfile->raw_contents + mep->entry->source_file_offset);
304 ptr = symfile->raw_contents + mep->entry->line_number_table_offset;
306 lne = (MonoSymbolFileLineNumberEntry *) ptr;
308 for (i = 0; i < mep->entry->num_line_numbers; i++, lne++) {
309 if (lne->offset < offset)
313 *line_number = lne->row;
318 } else if (source_file) {
319 gchar *retval = g_strdup_printf ("%s:%d", source_file, lne->row);
320 g_free (source_file);
323 return g_strdup_printf ("%d", lne->row);
330 mono_debug_symfile_add_method (MonoSymbolFile *symfile, MonoMethod *method)
332 MonoSymbolFileMethodEntryPriv *mep;
333 MonoSymbolFileMethodAddress *address;
334 MonoDebugVarInfo *var_table;
335 MonoDebugRangeInfo *range;
336 guint32 size, num_variables, variable_size, variable_offset;
337 guint32 type_size, type_offset, *type_index_table;
338 gpointer *type_table;
342 mep = g_hash_table_lookup (symfile->_priv->method_table, method);
347 mep->minfo = g_hash_table_lookup (symfile->_priv->method_hash, mep->method);
352 if (!mep->minfo->jit)
355 symfile->generation++;
357 size = sizeof (MonoSymbolFileMethodAddress);
359 num_variables = mep->entry->num_parameters + mep->entry->num_locals;
360 if (mep->entry->this_type_index)
363 variable_size = num_variables * sizeof (MonoDebugVarInfo);
364 variable_offset = size;
365 size += variable_size;
367 type_size = num_variables * sizeof (gpointer);
371 address = g_malloc0 (size);
372 ptr = (guint8 *) address;
374 address->size = size;
375 address->start_address = GPOINTER_TO_UINT (mep->minfo->jit->code_start);
376 address->end_address = GPOINTER_TO_UINT (mep->minfo->jit->code_start + mep->minfo->jit->code_size);
377 address->variable_table_offset = variable_offset;
378 address->type_table_offset = type_offset;
380 if (mep->minfo->jit->line_numbers) {
381 address->num_line_numbers = mep->minfo->jit->line_numbers->len;
382 address->line_numbers = (MonoDebugLineNumberEntry *) mep->minfo->jit->line_numbers->data;
383 address->line_number_size = address->num_line_numbers * sizeof (MonoDebugLineNumberEntry);
386 range = allocate_range_entry (symfile);
387 range->file_offset = mep->minfo->file_offset;
388 range->start_address = address->start_address;
389 range->end_address = address->end_address;
390 range->dynamic_data = address;
391 range->dynamic_size = size;
393 var_table = (MonoDebugVarInfo *) (ptr + variable_offset);
394 type_table = (gpointer *) (ptr + type_offset);
396 type_index_table = (guint32 *)
397 (symfile->raw_contents + mep->entry->type_index_table_offset);
399 if (mep->entry->this_type_index) {
400 if (!mep->minfo->jit->this_var) {
401 g_warning (G_STRLOC ": Method %s.%s doesn't have `this'.",
402 mep->method->klass->name, mep->method->name);
405 *var_table++ = *mep->minfo->jit->this_var;
406 *type_table++ = write_type (&method->klass->this_arg);
410 if (mep->minfo->jit->num_params != mep->entry->num_parameters) {
411 g_warning (G_STRLOC ": Method %s.%s has %d parameters, but symbol file claims it has %d.",
412 mep->method->klass->name, mep->method->name, mep->minfo->jit->num_params,
413 mep->entry->num_parameters);
414 var_table += mep->entry->num_parameters;
416 for (i = 0; i < mep->minfo->jit->num_params; i++) {
417 *var_table++ = mep->minfo->jit->params [i];
418 *type_table++ = write_type (method->signature->params [i]);
422 if (mep->minfo->jit->num_locals != mep->entry->num_locals) {
424 g_warning (G_STRLOC ": Method %s.%s has %d locals, but symbol file claims it has %d.",
425 mep->method->klass->name, mep->method->name, mep->minfo->jit->num_locals,
426 mep->entry->num_locals);
428 var_table += mep->entry->num_locals;
430 for (i = 0; i < mep->minfo->jit->num_locals; i++)
431 *var_table++ = mep->minfo->jit->locals [i];
435 mono_debug_symfile_add_type (MonoSymbolFile *symfile, MonoClass *klass)
437 MonoDebugTypeInfo *info = allocate_type_entry (symfile);
441 info->token = klass->element_class->type_token;
442 info->rank = klass->rank;
444 info->token = klass->type_token;
445 info->type_info = write_type (&klass->this_arg);
449 free_method_entry (MonoSymbolFileMethodEntryPriv *mep)
457 create_method (MonoSymbolFile *symfile, guint32 token, MonoMethod *method)
459 MonoSymbolFileMethodEntryPriv *mep;
460 MonoDebugMethodInfo *minfo;
462 g_assert (method->klass->image == symfile->_priv->image);
464 mep = g_new0 (MonoSymbolFileMethodEntryPriv, 1);
465 mep->entry = g_new0 (MonoSymbolFileMethodEntry, 1);
466 mep->entry->token = token;
467 mep->entry->source_file_offset = symfile->_priv->offset_table->source_table_offset;
469 mep->method_name_offset = symfile->_priv->string_table_size;
470 mep->name = g_strdup_printf ("%s%s.%s", method->klass->name_space,
471 method->klass->name, method->name);
472 symfile->_priv->string_table_size += strlen (mep->name) + 1;
474 minfo = g_hash_table_lookup (symfile->_priv->method_hash, method);
475 g_assert (minfo && (minfo->method == method));
476 minfo->symfile = symfile;
479 mep->method = method;
481 symfile->_priv->offset_table->method_count++;
483 g_hash_table_insert (symfile->_priv->method_table, method, mep);
487 write_method (gpointer key, gpointer value, gpointer user_data)
489 MonoSymbolFile *symfile = (MonoSymbolFile *) user_data;
490 MonoSymbolFileMethodEntryPriv *mep = (MonoSymbolFileMethodEntryPriv *) value;
492 if (symfile->_priv->error)
495 mep->minfo->file_offset = lseek (symfile->_priv->fd, 0, SEEK_CUR);
497 if (write (symfile->_priv->fd, mep->entry, sizeof (MonoSymbolFileMethodEntry)) < 0) {
498 symfile->_priv->error = TRUE;
504 create_methods (MonoSymbolFile *symfile)
506 MonoImage *image = symfile->_priv->image;
507 MonoTableInfo *table = &image->tables [MONO_TABLE_METHOD];
510 for (idx = 1; idx <= table->rows; idx++) {
511 guint32 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
512 MonoMethod *method = mono_get_method (image, token, NULL);
514 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
515 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
516 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
519 if (method->wrapper_type != MONO_WRAPPER_NONE)
522 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
523 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
524 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
525 g_assert_not_reached ();
527 if (!((MonoMethodNormal *) method)->header) {
528 g_warning (G_STRLOC ": Internal error: method %s.%s doesn't have a header",
529 method->klass->name, method->name);
533 create_method (symfile, token, method);
538 create_symfile (MonoSymbolFile *symfile, gboolean emit_warnings)
540 MonoSymbolFilePriv *priv = symfile->_priv;
546 priv->fd = g_file_open_tmp (NULL, &priv->file_name, NULL);
547 if (priv->fd == -1) {
549 g_warning ("Can't create symbol file");
553 symfile->symbol_file = g_strdup (priv->file_name);
555 magic = MONO_SYMBOL_FILE_MAGIC;
556 if (write (priv->fd, &magic, sizeof (magic)) < 0)
559 version = MONO_SYMBOL_FILE_VERSION;
560 if (write (priv->fd, &version, sizeof (version)) < 0)
563 offset = lseek (priv->fd, 0, SEEK_CUR);
565 priv->offset_table = g_new0 (MonoSymbolFileOffsetTable, 1);
566 if (write (priv->fd, priv->offset_table, sizeof (MonoSymbolFileOffsetTable)) < 0)
570 // Write source file table.
572 if (priv->source_file) {
573 priv->offset_table->source_table_offset = lseek (priv->fd, 0, SEEK_CUR);
574 if (!write_string (priv->fd, priv->source_file))
576 priv->offset_table->source_table_size = lseek (priv->fd, 0, SEEK_CUR) -
577 priv->offset_table->source_table_offset;
581 // Create method table.
584 priv->method_table = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
585 (GDestroyNotify) free_method_entry);
587 create_methods (symfile);
590 // Write method table.
593 priv->offset_table->method_table_offset = lseek (priv->fd, 0, SEEK_CUR);
595 g_hash_table_foreach (priv->method_table, write_method, symfile);
599 priv->offset_table->method_table_size = lseek (priv->fd, 0, SEEK_CUR) -
600 priv->offset_table->method_table_offset;
603 // Write offset table.
606 symfile->raw_contents_size = lseek (priv->fd, 0, SEEK_CUR);
608 lseek (priv->fd, offset, SEEK_SET);
609 if (write (priv->fd, priv->offset_table, sizeof (MonoSymbolFileOffsetTable)) < 0)
612 lseek (priv->fd, symfile->raw_contents_size, SEEK_SET);
614 ptr = mono_raw_buffer_load (priv->fd, TRUE, 0, symfile->raw_contents_size);
618 symfile->raw_contents = ptr;
620 if (!write_string_table (symfile))
627 mono_debug_create_mono_symbol_file (MonoImage *image, GHashTable *method_hash)
629 MonoSymbolFile *symfile;
631 symfile = g_new0 (MonoSymbolFile, 1);
632 symfile->magic = MONO_SYMBOL_FILE_MAGIC;
633 symfile->version = MONO_SYMBOL_FILE_VERSION;
634 symfile->dynamic_magic = MONO_SYMBOL_FILE_DYNAMIC_MAGIC;
635 symfile->dynamic_version = MONO_SYMBOL_FILE_DYNAMIC_VERSION;
636 symfile->is_dynamic = TRUE;
637 symfile->image_file = g_strdup (image->name);
639 symfile->_priv = g_new0 (MonoSymbolFilePriv, 1);
640 symfile->_priv->image = image;
641 symfile->_priv->method_hash = method_hash;
643 if (!create_symfile (symfile, TRUE)) {
644 mono_debug_close_mono_symbol_file (symfile);
651 MonoDebugMethodInfo *
652 mono_debug_find_method (MonoSymbolFile *symfile, MonoMethod *method)
654 return g_hash_table_lookup (symfile->_priv->method_hash, method);
658 write_method_name (gpointer key, gpointer value, gpointer user_data)
660 MonoSymbolFile *symfile = (MonoSymbolFile *) user_data;
661 MonoSymbolFileMethodEntryPriv *mep = (MonoSymbolFileMethodEntryPriv *) value;
662 MonoSymbolFilePriv *priv = symfile->_priv;
663 guint8 *offset_ptr, *string_ptr;
666 offset = mep->method_name_offset + priv->string_offset_size;
668 offset_ptr = symfile->string_table + mep->index * 4;
669 string_ptr = symfile->string_table + offset;
671 *((guint32 *) offset_ptr) = offset;
672 strcpy (string_ptr, mep->name);
676 write_string_table (MonoSymbolFile *symfile)
678 MonoSymbolFilePriv *priv = symfile->_priv;
680 priv->string_offset_size = priv->offset_table->method_count * 4;
682 symfile->string_table_size = priv->string_table_size + priv->string_offset_size;
683 symfile->string_table = g_malloc0 (symfile->string_table_size);
685 g_hash_table_foreach (symfile->_priv->method_table, write_method_name, symfile);
689 MonoReflectionMethod *
690 ves_icall_MonoDebugger_GetMethod (MonoReflectionAssembly *assembly, guint32 token)
694 method = mono_get_method (assembly->assembly->image, token, NULL);
696 return mono_method_get_object (mono_domain_get (), method, NULL);
700 ves_icall_MonoDebugger_GetType (MonoReflectionAssembly *assembly, guint32 token)
704 klass = g_hash_table_lookup (assembly->assembly->image->class_cache, GUINT_TO_POINTER (token));
706 g_message (G_STRLOC ": %x", token);
710 return mono_type_get_object (mono_domain_get (), &klass->byval_arg);
714 ves_icall_MonoDebugger_GetLocalTypeFromSignature (MonoReflectionAssembly *assembly, MonoArray *signature)
722 MONO_CHECK_ARG_NULL (assembly);
723 MONO_CHECK_ARG_NULL (signature);
725 domain = mono_domain_get();
726 image = assembly->assembly->image;
728 ptr = mono_array_addr (signature, char, 0);
729 g_assert (*ptr++ == 0x07);
730 len = mono_metadata_decode_value (ptr, &ptr);
733 type = mono_metadata_parse_type (image, MONO_PARSE_LOCAL, 0, ptr, &ptr);
735 return mono_type_get_object (domain, type);
738 static MonoDebugRangeInfo *
739 allocate_range_entry (MonoSymbolFile *symfile)
741 MonoDebugRangeInfo *retval;
742 guint32 size, chunks;
744 symfile->range_entry_size = sizeof (MonoDebugRangeInfo);
746 if (!symfile->range_table) {
747 size = sizeof (MonoDebugRangeInfo) * RANGE_TABLE_CHUNK_SIZE;
748 symfile->range_table = g_malloc0 (size);
749 symfile->num_range_entries = 1;
750 return symfile->range_table;
753 if (!((symfile->num_range_entries + 1) % RANGE_TABLE_CHUNK_SIZE)) {
754 chunks = (symfile->num_range_entries + 1) / RANGE_TABLE_CHUNK_SIZE;
755 size = sizeof (MonoDebugRangeInfo) * RANGE_TABLE_CHUNK_SIZE * (chunks + 1);
757 symfile->range_table = g_realloc (symfile->range_table, size);
760 retval = symfile->range_table + symfile->num_range_entries;
761 symfile->num_range_entries++;
765 static MonoDebugTypeInfo *
766 allocate_type_entry (MonoSymbolFile *symfile)
768 MonoDebugTypeInfo *retval;
769 guint32 size, chunks;
771 symfile->type_entry_size = sizeof (MonoDebugTypeInfo);
773 if (!symfile->type_table) {
774 size = sizeof (MonoDebugTypeInfo) * TYPE_TABLE_CHUNK_SIZE;
775 symfile->type_table = g_malloc0 (size);
776 symfile->num_type_entries = 1;
777 return symfile->type_table;
780 if (!((symfile->num_type_entries + 1) % TYPE_TABLE_CHUNK_SIZE)) {
781 chunks = (symfile->num_type_entries + 1) / TYPE_TABLE_CHUNK_SIZE;
782 size = sizeof (MonoDebugTypeInfo) * TYPE_TABLE_CHUNK_SIZE * (chunks + 1);
784 symfile->type_table = g_realloc (symfile->type_table, size);
787 retval = symfile->type_table + symfile->num_type_entries;
788 symfile->num_type_entries++;
793 write_simple_type (MonoType *type)
795 guint8 buffer [BUFSIZ], *ptr = buffer, *retval;
799 type_table = g_hash_table_new (g_direct_hash, g_direct_equal);
801 retval = g_hash_table_lookup (type_table, type);
805 switch (type->type) {
806 case MONO_TYPE_BOOLEAN:
809 *((int *) ptr)++ = 1;
815 *((int *) ptr)++ = 2;
821 *((int *) ptr)++ = 4;
827 *((int *) ptr)++ = 8;
830 case MONO_TYPE_STRING: {
833 *((int *) ptr)++ = -8;
834 *((guint32 *) ptr)++ = sizeof (MonoString);
836 *ptr++ = (guint8*)&string.length - (guint8*)&string;
837 *ptr++ = sizeof (string.length);
838 *ptr++ = (guint8*)&string.chars - (guint8*)&string;
848 retval = g_malloc0 (size + 4);
849 memcpy (retval + 4, buffer, size);
850 *((int *) retval) = size;
852 g_hash_table_insert (type_table, type, retval);
858 write_type (MonoType *type)
860 guint8 buffer [BUFSIZ], *ptr = buffer, *retval;
865 type_table = g_hash_table_new (g_direct_hash, g_direct_equal);
867 retval = g_hash_table_lookup (type_table, type);
871 retval = write_simple_type (type);
875 switch (type->type) {
876 case MONO_TYPE_SZARRAY:
877 size = 8 + sizeof (int) + sizeof (gpointer);
880 case MONO_TYPE_ARRAY:
881 size = 15 + sizeof (int) + sizeof (gpointer);
884 case MONO_TYPE_VALUETYPE:
885 case MONO_TYPE_CLASS: {
886 MonoClass *klass = type->data.klass;
889 mono_class_init (klass);
890 if (klass->enumtype) {
891 size = 5 + sizeof (int) + sizeof (gpointer);
895 for (i = 0; i < klass->field.count; i++)
896 if (!(klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
899 size = 14 + sizeof (int) + num_fields * (4 + sizeof (gpointer));
901 if (type->type == MONO_TYPE_CLASS)
902 size += sizeof (gpointer);
906 case MONO_TYPE_OBJECT:
907 size = 5 + sizeof (int);
915 retval = g_malloc0 (size + 4);
916 memcpy (retval + 4, buffer, size);
917 *((int *) retval) = size;
919 g_hash_table_insert (type_table, type, retval);
923 switch (type->type) {
924 case MONO_TYPE_SZARRAY: {
927 *((int *) ptr)++ = -8 - sizeof (gpointer);
928 *((guint32 *) ptr)++ = sizeof (MonoArray);
930 *ptr++ = (guint8*)&array.max_length - (guint8*)&array;
931 *ptr++ = sizeof (array.max_length);
932 *ptr++ = (guint8*)&array.vector - (guint8*)&array;
933 *((gpointer *) ptr)++ = write_type (type->data.type);
937 case MONO_TYPE_ARRAY: {
939 MonoArrayBounds bounds;
941 *((int *) ptr)++ = -15 - sizeof (gpointer);
942 *((guint32 *) ptr)++ = sizeof (MonoArray);
944 *ptr++ = (guint8*)&array.max_length - (guint8*)&array;
945 *ptr++ = sizeof (array.max_length);
946 *ptr++ = (guint8*)&array.vector - (guint8*)&array;
947 *ptr++ = type->data.array->rank;
948 *ptr++ = (guint8*)&array.bounds - (guint8*)&array;
949 *ptr++ = sizeof (MonoArrayBounds);
950 *ptr++ = (guint8*)&bounds.lower_bound - (guint8*)&bounds;
951 *ptr++ = sizeof (bounds.lower_bound);
952 *ptr++ = (guint8*)&bounds.length - (guint8*)&bounds;
953 *ptr++ = sizeof (bounds.length);
954 *((gpointer *) ptr)++ = write_type (type->data.array->type);
958 case MONO_TYPE_VALUETYPE:
959 case MONO_TYPE_CLASS: {
960 MonoClass *klass = type->data.klass;
961 int base_offset = type->type == MONO_TYPE_CLASS ? 0 : - sizeof (MonoObject);
964 mono_class_init (klass);
965 if (klass->enumtype) {
966 *((int *) ptr)++ = -5 - sizeof (gpointer);
967 *((guint32 *) ptr)++ = sizeof (MonoObject);
969 *((gpointer *) ptr)++ = write_type (klass->enum_basetype);
973 *((int *) ptr)++ = -14 - num_fields * (4 + sizeof (gpointer));
974 *((guint32 *) ptr)++ = klass->instance_size + base_offset;
975 *ptr++ = type->type == MONO_TYPE_CLASS ? 6 : 5;
976 *ptr++ = type->type == MONO_TYPE_CLASS;
977 *((guint32 *) ptr)++ = num_fields;
978 *((guint32 *) ptr)++ = num_fields * (4 + sizeof (gpointer));
979 for (i = 0; i < klass->field.count; i++) {
980 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
983 *((guint32 *) ptr)++ = klass->fields [i].offset + base_offset;
984 *((gpointer *) ptr)++ = write_type (klass->fields [i].type);
987 if (type->type == MONO_TYPE_CLASS) {
989 *((gpointer *) ptr)++ = write_type (&klass->parent->this_arg);
991 *((gpointer *) ptr)++ = NULL;
997 case MONO_TYPE_OBJECT:
998 *((int *) ptr)++ = -5;
999 *((guint32 *) ptr)++ = sizeof (MonoObject);
1004 g_message (G_STRLOC ": %p - %x,%x,%x", type, type->attrs, type->type, type->byref);
1006 *((int *) ptr)++ = -1;