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 CLASS_TABLE_CHUNK_SIZE 256
19 #define TYPE_TABLE_PTR_CHUNK_SIZE 256
20 #define TYPE_TABLE_CHUNK_SIZE 65536
22 struct MonoSymbolFilePriv
24 const guint8 *raw_contents;
25 int raw_contents_size;
27 GHashTable *method_table;
28 GHashTable *method_hash;
29 MonoSymbolFileOffsetTable *offset_table;
35 MonoDebugMethodInfo *minfo;
36 MonoSymbolFileMethodEntry *entry;
37 guint32 method_name_offset;
40 } MonoSymbolFileMethodEntryPriv;
42 static GHashTable *type_table;
43 static GHashTable *class_table;
45 MonoGlobalSymbolFile *mono_debugger_global_symbol_file = NULL;
47 static MonoDebugRangeInfo *allocate_range_entry (MonoSymbolFile *symfile);
48 static MonoDebugClassInfo *allocate_class_entry (MonoSymbolFile *symfile);
49 static guint32 allocate_type_entry (MonoGlobalSymbolFile *global_symfile, guint32 size, guint8 **ptr);
50 static guint32 write_type (MonoGlobalSymbolFile *global_symfile, MonoType *type);
53 free_method_info (MonoDebugMethodInfo *minfo)
60 get_class_name (MonoClass *klass)
62 if (klass->nested_in) {
63 gchar *parent_name = get_class_name (klass->nested_in);
64 gchar *name = g_strdup_printf ("%s.%s", parent_name, klass->name);
69 return g_strdup_printf ("%s%s%s", klass->name_space,
70 klass->name_space [0] ? "." : "", klass->name);
74 load_symfile (MonoSymbolFile *symfile)
76 MonoSymbolFilePriv *priv = symfile->_priv;
77 MonoSymbolFileMethodEntry *me;
78 MonoSymbolFileMethodIndexEntry *ie;
79 const char *ptr, *start;
84 if (!mono_debugger_global_symbol_file)
85 mono_debugger_global_symbol_file = g_new0 (MonoGlobalSymbolFile, 1);
86 symfile->global = mono_debugger_global_symbol_file;
88 ptr = start = priv->raw_contents;
92 magic = *((guint64 *) ptr)++;
93 if (magic != MONO_SYMBOL_FILE_MAGIC) {
94 g_warning ("Symbol file %s has is not a mono symbol file", symfile->image_file);
98 version = *((guint32 *) ptr)++;
99 if (version != MONO_SYMBOL_FILE_VERSION) {
100 g_warning ("Symbol file %s has incorrect version "
101 "(expected %d, got %ld)", symfile->image_file,
102 MONO_SYMBOL_FILE_VERSION, version);
106 priv->offset_table = (MonoSymbolFileOffsetTable *) ptr;
108 mono_debug_symfile_add_type (symfile, mono_defaults.object_class);
115 priv->method_table = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
116 (GDestroyNotify) g_free);
117 priv->method_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
118 (GDestroyNotify) free_method_info);
120 ie = (MonoSymbolFileMethodIndexEntry *)
121 (priv->raw_contents + priv->offset_table->method_table_offset);
123 for (i = 0; i < priv->offset_table->method_count; i++, me++, ie++) {
125 MonoSymbolFileMethodEntryPriv *mep;
126 MonoDebugMethodInfo *minfo;
128 me = (MonoSymbolFileMethodEntry *) (priv->raw_contents + ie->file_offset);
130 method = mono_get_method (priv->image, me->token, NULL);
135 minfo = g_new0 (MonoDebugMethodInfo, 1);
136 minfo->index = i + 1;
137 minfo->method = method;
138 minfo->symfile = symfile;
139 minfo->num_il_offsets = me->num_line_numbers;
140 minfo->il_offsets = (MonoSymbolFileLineNumberEntry *)
141 (priv->raw_contents + me->line_number_table_offset);
143 mep = g_new0 (MonoSymbolFileMethodEntryPriv, 1);
144 mep->method = method;
149 g_hash_table_insert (priv->method_table, method, mep);
150 g_hash_table_insert (priv->method_hash, method, minfo);
157 open_symfile (MonoImage *image, guint32 *size)
159 MonoTableInfo *table = &image->tables [MONO_TABLE_MANIFESTRESOURCE];
161 guint32 cols [MONO_MANIFEST_SIZE];
164 for (i = 0; i < table->rows; ++i) {
165 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
166 val = mono_metadata_string_heap (image, cols [MONO_MANIFEST_NAME]);
167 if (!strcmp (val, "MonoSymbolFile"))
170 if (i == table->rows)
172 g_assert (!cols [MONO_MANIFEST_IMPLEMENTATION]);
174 return mono_image_get_resource (image, cols [MONO_MANIFEST_OFFSET], size);
178 mono_debug_open_mono_symbol_file (MonoImage *image, gboolean create_symfile)
180 MonoSymbolFile *symfile;
181 MonoSymbolFilePriv *priv;
183 symfile = g_new0 (MonoSymbolFile, 1);
184 symfile->dynamic_magic = MONO_SYMBOL_FILE_DYNAMIC_MAGIC;
185 symfile->dynamic_version = MONO_SYMBOL_FILE_DYNAMIC_VERSION;
186 symfile->image_file = image->name;
188 symfile->_priv = priv = g_new0 (MonoSymbolFilePriv, 1);
191 priv->raw_contents = open_symfile (image, &priv->raw_contents_size);
193 if (load_symfile (symfile))
195 else if (!create_symfile) {
196 mono_debug_close_mono_symbol_file (symfile);
200 mono_debug_symfile_add_type (symfile, mono_defaults.object_class);
206 mono_debug_close_mono_symbol_file (MonoSymbolFile *symfile)
208 MonoSymbolFilePriv *priv;
213 priv = symfile->_priv;
215 if (priv->method_table)
216 g_hash_table_destroy (priv->method_table);
217 if (priv->method_hash)
218 g_hash_table_destroy (priv->method_hash);
225 read_string (const char *ptr)
227 int len = *((guint32 *) ptr)++;
229 return g_filename_from_utf8 (ptr, len, NULL, NULL, NULL);
233 mono_debug_find_source_location (MonoSymbolFile *symfile, MonoMethod *method, guint32 offset,
234 guint32 *line_number)
236 MonoSymbolFilePriv *priv = symfile->_priv;
237 MonoSymbolFileLineNumberEntry *lne;
238 MonoSymbolFileMethodEntryPriv *mep;
239 gchar *source_file = NULL;
243 if (!priv->method_table)
246 mep = g_hash_table_lookup (priv->method_table, method);
250 if (mep->entry->source_index) {
251 int offset = priv->offset_table->source_table_offset +
252 (mep->entry->source_index - 1) * sizeof (MonoSymbolFileSourceEntry);
253 MonoSymbolFileSourceEntry *se = (MonoSymbolFileSourceEntry *) (priv->raw_contents + offset);
255 source_file = read_string (priv->raw_contents + se->name_offset);
258 ptr = priv->raw_contents + mep->entry->line_number_table_offset;
260 lne = (MonoSymbolFileLineNumberEntry *) ptr;
262 for (i = 0; i < mep->entry->num_line_numbers; i++, lne++) {
263 if (lne->offset < offset)
267 *line_number = lne->row;
272 } else if (source_file) {
273 gchar *retval = g_strdup_printf ("%s:%d", source_file, lne->row);
274 g_free (source_file);
277 return g_strdup_printf ("%d", lne->row);
284 mono_debug_symfile_add_method (MonoSymbolFile *symfile, MonoMethod *method)
286 MonoSymbolFileMethodEntryPriv *mep;
287 MonoSymbolFileMethodAddress *address;
288 MonoDebugVarInfo *var_table;
289 MonoDebugRangeInfo *range;
290 MonoMethodHeader *header;
291 guint32 size, num_variables, variable_size, variable_offset;
292 guint32 type_size, type_offset, *type_index_table;
293 guint32 line_size, line_offset, has_this;
294 MonoDebugLineNumberEntry *line_table;
299 if (!symfile->_priv->method_table)
302 header = ((MonoMethodNormal *) method)->header;
304 mep = g_hash_table_lookup (symfile->_priv->method_table, method);
309 mep->minfo = g_hash_table_lookup (symfile->_priv->method_hash, mep->method);
314 if (!mep->minfo->jit)
317 symfile->generation++;
319 size = sizeof (MonoSymbolFileMethodAddress);
321 num_variables = mep->entry->num_parameters + mep->entry->num_locals;
322 has_this = mep->minfo->jit->this_var != NULL;
324 variable_size = (num_variables + has_this) * sizeof (MonoDebugVarInfo);
325 variable_offset = size;
326 size += variable_size;
328 type_size = (num_variables + 1) * sizeof (gpointer);
332 if (mep->minfo->jit->line_numbers) {
334 line_size = mep->minfo->jit->line_numbers->len * sizeof (MonoDebugLineNumberEntry);
338 address = g_malloc0 (size);
339 ptr = (guint8 *) address;
341 address->size = size;
342 address->has_this = has_this;
343 address->start_address = mep->minfo->jit->code_start;
344 address->end_address = mep->minfo->jit->code_start + mep->minfo->jit->code_size;
345 address->method_start_address = address->start_address + mep->minfo->jit->prologue_end;
346 address->method_end_address = address->start_address + mep->minfo->jit->epilogue_begin;
347 address->wrapper_address = mep->minfo->jit->wrapper_addr;
348 address->variable_table_offset = variable_offset;
349 address->type_table_offset = type_offset;
351 if (mep->minfo->jit->line_numbers) {
352 address->num_line_numbers = mep->minfo->jit->line_numbers->len;
353 address->line_number_offset = line_offset;
355 line_table = (MonoDebugLineNumberEntry *) (ptr + line_offset);
356 memcpy (line_table, mep->minfo->jit->line_numbers->data, line_size);
359 range = allocate_range_entry (symfile);
360 range->index = mep->minfo->index;
361 range->start_address = address->start_address;
362 range->end_address = address->end_address;
363 range->dynamic_data = address;
364 range->dynamic_size = size;
366 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
367 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
368 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
371 var_table = (MonoDebugVarInfo *) (ptr + variable_offset);
372 type_table = (guint32 *) (ptr + type_offset);
374 type_index_table = (guint32 *)
375 (symfile->_priv->raw_contents + mep->entry->type_index_table_offset);
377 if (mep->minfo->jit->this_var)
378 *var_table++ = *mep->minfo->jit->this_var;
379 *type_table++ = write_type (symfile->global, &method->klass->this_arg);
381 if (mep->minfo->jit->num_params != mep->entry->num_parameters) {
382 g_warning (G_STRLOC ": Method %s.%s has %d parameters, but symbol file claims it has %d.",
383 mep->method->klass->name, mep->method->name, mep->minfo->jit->num_params,
384 mep->entry->num_parameters);
386 var_table += mep->entry->num_parameters;
388 for (i = 0; i < mep->minfo->jit->num_params; i++) {
389 *var_table++ = mep->minfo->jit->params [i];
390 *type_table++ = write_type (symfile->global, method->signature->params [i]);
394 if (mep->minfo->jit->num_locals < mep->entry->num_locals) {
396 g_warning (G_STRLOC ": Method %s.%s has %d locals, but symbol file claims it has %d.",
397 mep->method->klass->name, mep->method->name, mep->minfo->jit->num_locals,
398 mep->entry->num_locals);
400 var_table += mep->entry->num_locals;
402 g_assert ((header != NULL) || (mep->entry->num_locals == 0));
403 for (i = 0; i < mep->entry->num_locals; i++) {
404 *var_table++ = mep->minfo->jit->locals [i];
405 *type_table++ = write_type (symfile->global, header->locals [i]);
411 mono_debug_symfile_add_type (MonoSymbolFile *symfile, MonoClass *klass)
413 MonoDebugClassInfo *info;
416 class_table = g_hash_table_new (g_direct_hash, g_direct_equal);
418 /* We write typeof (object) into each symbol file's type table. */
419 if ((klass != mono_defaults.object_class) && g_hash_table_lookup (class_table, klass))
422 symfile->generation++;
424 info = allocate_class_entry (symfile);
427 info->token = klass->element_class->type_token;
428 info->rank = klass->rank;
430 info->token = klass->type_token;
431 info->type_info = write_type (symfile->global, &klass->this_arg);
434 MonoDebugMethodInfo *
435 mono_debug_find_method (MonoSymbolFile *symfile, MonoMethod *method)
437 if (!symfile->_priv->method_hash)
440 return g_hash_table_lookup (symfile->_priv->method_hash, method);
443 MonoReflectionMethod *
444 ves_icall_MonoDebugger_GetMethod (MonoReflectionAssembly *assembly, guint32 token)
448 method = mono_get_method (assembly->assembly->image, token, NULL);
450 return mono_method_get_object (mono_domain_get (), method, NULL);
454 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionAssembly *assembly, MonoReflectionMethod *method)
456 return method->method->token;
460 ves_icall_MonoDebugger_GetType (MonoReflectionAssembly *assembly, guint32 token)
464 klass = mono_class_get (assembly->assembly->image, token);
466 g_warning (G_STRLOC ": %x", token);
470 return mono_type_get_object (mono_domain_get (), &klass->byval_arg);
474 ves_icall_MonoDebugger_GetLocalTypeFromSignature (MonoReflectionAssembly *assembly, MonoArray *signature)
482 MONO_CHECK_ARG_NULL (assembly);
483 MONO_CHECK_ARG_NULL (signature);
485 domain = mono_domain_get();
486 image = assembly->assembly->image;
488 ptr = mono_array_addr (signature, char, 0);
489 g_assert (*ptr++ == 0x07);
490 len = mono_metadata_decode_value (ptr, &ptr);
493 type = mono_metadata_parse_type (image, MONO_PARSE_LOCAL, 0, ptr, &ptr);
495 return mono_type_get_object (domain, type);
498 static MonoDebugRangeInfo *
499 allocate_range_entry (MonoSymbolFile *symfile)
501 MonoDebugRangeInfo *retval;
502 guint32 size, chunks;
504 symfile->range_entry_size = sizeof (MonoDebugRangeInfo);
506 if (!symfile->range_table) {
507 size = sizeof (MonoDebugRangeInfo) * RANGE_TABLE_CHUNK_SIZE;
508 symfile->range_table = g_malloc0 (size);
509 symfile->num_range_entries = 1;
510 return symfile->range_table;
513 if (!((symfile->num_range_entries + 1) % RANGE_TABLE_CHUNK_SIZE)) {
514 chunks = (symfile->num_range_entries + 1) / RANGE_TABLE_CHUNK_SIZE;
515 size = sizeof (MonoDebugRangeInfo) * RANGE_TABLE_CHUNK_SIZE * (chunks + 1);
517 symfile->range_table = g_realloc (symfile->range_table, size);
520 retval = symfile->range_table + symfile->num_range_entries;
521 symfile->num_range_entries++;
525 static MonoDebugClassInfo *
526 allocate_class_entry (MonoSymbolFile *symfile)
528 MonoDebugClassInfo *retval;
529 guint32 size, chunks;
531 symfile->class_entry_size = sizeof (MonoDebugClassInfo);
533 if (!symfile->class_table) {
534 size = sizeof (MonoDebugClassInfo) * CLASS_TABLE_CHUNK_SIZE;
535 symfile->class_table = g_malloc0 (size);
536 symfile->num_class_entries = 1;
537 return symfile->class_table;
540 if (!((symfile->num_class_entries + 1) % CLASS_TABLE_CHUNK_SIZE)) {
541 chunks = (symfile->num_class_entries + 1) / CLASS_TABLE_CHUNK_SIZE;
542 size = sizeof (MonoDebugClassInfo) * CLASS_TABLE_CHUNK_SIZE * (chunks + 1);
544 symfile->class_table = g_realloc (symfile->class_table, size);
547 retval = symfile->class_table + symfile->num_class_entries;
548 symfile->num_class_entries++;
553 * Allocate a new entry of size `size' in the type table.
554 * Returns the global offset which is to be used to reference this type and
555 * a pointer (in the `ptr' argument) which is to be used to write the type.
558 allocate_type_entry (MonoGlobalSymbolFile *global, guint32 size, guint8 **ptr)
563 g_assert (size + 4 < TYPE_TABLE_CHUNK_SIZE);
564 g_assert (ptr != NULL);
566 /* Initialize things if necessary. */
567 if (!global->current_type_table) {
568 global->current_type_table = g_malloc0 (TYPE_TABLE_CHUNK_SIZE);
569 global->type_table_size = TYPE_TABLE_CHUNK_SIZE;
570 global->type_table_chunk_size = TYPE_TABLE_CHUNK_SIZE;
571 global->type_table_offset = 1;
575 /* First let's check whether there's still enough room in the current_type_table. */
576 if (global->type_table_offset + size + 4 < global->type_table_size) {
577 retval = global->type_table_offset;
578 global->type_table_offset += size + 4;
579 data = ((guint8 *) global->current_type_table) + retval - global->type_table_start;
580 *((gint32 *) data)++ = size;
585 /* Add the current_type_table to the type_tables vector and ... */
586 if (!global->type_tables) {
587 guint32 tsize = sizeof (gpointer) * TYPE_TABLE_PTR_CHUNK_SIZE;
588 global->type_tables = g_malloc0 (tsize);
591 if (!((global->num_type_tables + 1) % TYPE_TABLE_PTR_CHUNK_SIZE)) {
592 guint32 chunks = (global->num_type_tables + 1) / TYPE_TABLE_PTR_CHUNK_SIZE;
593 guint32 tsize = sizeof (gpointer) * TYPE_TABLE_PTR_CHUNK_SIZE * (chunks + 1);
595 global->type_tables = g_realloc (global->type_tables, tsize);
598 global->type_tables [global->num_type_tables++] = global->current_type_table;
600 /* .... allocate a new current_type_table. */
601 global->current_type_table = g_malloc0 (TYPE_TABLE_CHUNK_SIZE);
602 global->type_table_start = global->type_table_offset = global->type_table_size;
603 global->type_table_size += TYPE_TABLE_CHUNK_SIZE;
609 write_simple_type (MonoGlobalSymbolFile *global, MonoType *type)
611 guint8 buffer [BUFSIZ], *ptr = buffer;
612 guint32 size, offset;
615 type_table = g_hash_table_new (g_direct_hash, g_direct_equal);
617 offset = GPOINTER_TO_UINT (g_hash_table_lookup (type_table, type));
621 switch (type->type) {
622 case MONO_TYPE_BOOLEAN:
625 *((gint32 *) ptr)++ = 1;
631 *((gint32 *) ptr)++ = 2;
637 *((gint32 *) ptr)++ = 4;
643 *((gint32 *) ptr)++ = 8;
648 *((gint32 *) ptr)++ = sizeof (void *);
652 *((gint32 *) ptr)++ = 0;
655 case MONO_TYPE_STRING: {
658 *((gint32 *) ptr)++ = -8;
659 *((guint32 *) ptr)++ = sizeof (MonoString);
661 *ptr++ = (guint8*)&string.length - (guint8*)&string;
662 *ptr++ = sizeof (string.length);
663 *ptr++ = (guint8*)&string.chars - (guint8*)&string;
672 offset = allocate_type_entry (global, size, &ptr);
673 memcpy (ptr, buffer, size);
675 g_hash_table_insert (type_table, type, GUINT_TO_POINTER (offset));
681 * Adds type `type' to the type table and returns its offset.
684 write_type (MonoGlobalSymbolFile *global, MonoType *type)
686 guint8 buffer [BUFSIZ], *ptr = buffer, *old_ptr;
687 GPtrArray *methods = NULL;
688 int num_fields = 0, num_properties = 0, num_methods = 0;
689 int num_params = 0, kind;
690 guint32 size, data_size, offset;
691 MonoClass *klass = NULL;
694 type_table = g_hash_table_new (g_direct_hash, g_direct_equal);
696 class_table = g_hash_table_new (g_direct_hash, g_direct_equal);
698 offset = GPOINTER_TO_UINT (g_hash_table_lookup (type_table, type));
702 offset = write_simple_type (global, type);
707 if (kind == MONO_TYPE_OBJECT) {
708 klass = mono_defaults.object_class;
709 kind = MONO_TYPE_CLASS;
710 } else if ((kind == MONO_TYPE_VALUETYPE) || (kind == MONO_TYPE_CLASS)) {
711 klass = type->data.klass;
712 offset = GPOINTER_TO_UINT (g_hash_table_lookup (class_table, klass));
718 case MONO_TYPE_SZARRAY:
722 case MONO_TYPE_ARRAY:
726 case MONO_TYPE_VALUETYPE:
727 case MONO_TYPE_CLASS: {
728 GHashTable *method_slots = NULL;
731 if (klass->init_pending) {
736 mono_class_init (klass);
738 offset = GPOINTER_TO_UINT (g_hash_table_lookup (class_table, klass));
742 if (klass->enumtype) {
747 for (i = 0; i < klass->field.count; i++)
748 if (!(klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
751 for (i = 0; i < klass->property.count; i++)
752 if (!(klass->properties [i].attrs & FIELD_ATTRIBUTE_STATIC))
755 method_slots = g_hash_table_new (NULL, NULL);
756 methods = g_ptr_array_new ();
758 for (i = klass->method.count - 1; i >= 0; i--) {
759 MonoMethod *method = klass->methods [i];
761 if (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)
763 if (method->flags & (METHOD_ATTRIBUTE_STATIC | METHOD_ATTRIBUTE_SPECIAL_NAME))
765 if (!((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))
767 if (g_hash_table_lookup (method_slots, GUINT_TO_POINTER (method->slot)))
769 g_hash_table_insert (method_slots, GUINT_TO_POINTER (method->slot), method);
772 num_params += method->signature->param_count;
774 g_ptr_array_add (methods, method);
777 g_hash_table_destroy (method_slots);
779 size = 34 + num_fields * 8 + num_properties * (4 + 2 * sizeof (gpointer)) +
780 num_methods * (8 + sizeof (gpointer)) + num_params * 4;
782 if (kind == MONO_TYPE_CLASS)
795 offset = allocate_type_entry (global, data_size, &ptr);
798 g_hash_table_insert (type_table, type, GUINT_TO_POINTER (offset));
801 case MONO_TYPE_SZARRAY: {
804 *((gint32 *) ptr)++ = -size;
805 *((guint32 *) ptr)++ = sizeof (MonoArray);
807 *ptr++ = (guint8*)&array.max_length - (guint8*)&array;
808 *ptr++ = sizeof (array.max_length);
809 *ptr++ = (guint8*)&array.vector - (guint8*)&array;
810 *((guint32 *) ptr)++ = write_type (global, type->data.type);
814 case MONO_TYPE_ARRAY: {
816 MonoArrayBounds bounds;
818 *((gint32 *) ptr)++ = -size;
819 *((guint32 *) ptr)++ = sizeof (MonoArray);
821 *ptr++ = (guint8*)&array.max_length - (guint8*)&array;
822 *ptr++ = sizeof (array.max_length);
823 *ptr++ = (guint8*)&array.vector - (guint8*)&array;
824 *ptr++ = type->data.array->rank;
825 *ptr++ = (guint8*)&array.bounds - (guint8*)&array;
826 *ptr++ = sizeof (MonoArrayBounds);
827 *ptr++ = (guint8*)&bounds.lower_bound - (guint8*)&bounds;
828 *ptr++ = sizeof (bounds.lower_bound);
829 *ptr++ = (guint8*)&bounds.length - (guint8*)&bounds;
830 *ptr++ = sizeof (bounds.length);
831 *((guint32 *) ptr)++ = write_type (global, type->data.array->type);
835 case MONO_TYPE_VALUETYPE:
836 case MONO_TYPE_CLASS: {
837 int base_offset = kind == MONO_TYPE_CLASS ? 0 : - sizeof (MonoObject);
840 if (klass->init_pending) {
841 *((gint32 *) ptr)++ = -1;
845 g_hash_table_insert (class_table, klass, GUINT_TO_POINTER (offset));
847 if (klass->enumtype) {
848 *((gint32 *) ptr)++ = -size;
849 *((guint32 *) ptr)++ = sizeof (MonoObject);
851 *((guint32 *) ptr)++ = write_type (global, klass->enum_basetype);
855 *((gint32 *) ptr)++ = -size;
857 *((guint32 *) ptr)++ = klass->instance_size + base_offset;
858 if (type->type == MONO_TYPE_OBJECT)
861 *ptr++ = kind == MONO_TYPE_CLASS ? 6 : 5;
862 *ptr++ = kind == MONO_TYPE_CLASS;
863 *((guint32 *) ptr)++ = num_fields;
864 *((guint32 *) ptr)++ = num_fields * (4 + sizeof (gpointer));
865 *((guint32 *) ptr)++ = num_properties;
866 *((guint32 *) ptr)++ = num_properties * 3 * sizeof (gpointer);
867 *((guint32 *) ptr)++ = num_methods;
868 *((guint32 *) ptr)++ = num_methods * (4 + 2 * sizeof (gpointer)) +
869 num_params * sizeof (gpointer);
870 for (i = 0; i < klass->field.count; i++) {
871 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
874 *((guint32 *) ptr)++ = klass->fields [i].offset + base_offset;
875 *((guint32 *) ptr)++ = write_type (global, klass->fields [i].type);
878 for (i = 0; i < klass->property.count; i++) {
879 if (klass->properties [i].attrs & FIELD_ATTRIBUTE_STATIC)
882 if (klass->properties [i].get)
883 *((guint32 *) ptr)++ = write_type
884 (global, klass->properties [i].get->signature->ret);
886 *((guint32 *) ptr)++ = 0;
887 *((gpointer *) ptr)++ = klass->properties [i].get;
888 *((gpointer *) ptr)++ = klass->properties [i].set;
891 for (i = 0; i < methods->len; i++) {
892 MonoMethod *method = g_ptr_array_index (methods, i);
894 *((gpointer *) ptr)++ = method;
895 if ((method->signature->ret) && (method->signature->ret->type != MONO_TYPE_VOID))
896 *((guint32 *) ptr)++ = write_type (global, method->signature->ret);
898 *((guint32 *) ptr)++ = 0;
899 *((guint32 *) ptr)++ = method->signature->param_count;
900 for (j = 0; j < method->signature->param_count; j++)
901 *((guint32 *) ptr)++ = write_type (global, method->signature->params [j]);
904 g_ptr_array_free (methods, FALSE);
906 if (kind == MONO_TYPE_CLASS) {
908 *((guint32 *) ptr)++ = write_type (global, &klass->parent->this_arg);
910 *((guint32 *) ptr)++ = 0;
917 g_message (G_STRLOC ": %p - %x,%x,%x", type, type->attrs, kind, type->byref);
919 *((gint32 *) ptr)++ = -1;
923 if (ptr - old_ptr != data_size) {
924 g_warning (G_STRLOC ": %d,%d - %d", ptr - old_ptr, data_size, kind);
926 g_warning (G_STRLOC ": %s.%s", klass->name_space, klass->name);
927 g_assert_not_reached ();