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
19 struct MonoSymbolFilePriv
25 guint32 string_table_size;
26 guint32 string_offset_size;
28 GHashTable *method_table;
29 GHashTable *method_hash;
30 MonoSymbolFileOffsetTable *offset_table;
36 MonoDebugMethodInfo *minfo;
37 MonoSymbolFileMethodEntry *entry;
38 guint32 method_name_offset;
41 } MonoSymbolFileMethodEntryPriv;
43 static GHashTable *type_table;
45 static int write_string_table (MonoSymbolFile *symfile);
46 static int create_symfile (MonoSymbolFile *symfile, gboolean emit_warnings);
47 static void close_symfile (MonoSymbolFile *symfile);
48 static MonoDebugRangeInfo *allocate_range_entry (MonoSymbolFile *symfile);
49 static gpointer write_type (MonoSymbolFile *symfile, MonoType *type);
52 free_method_info (MonoDebugMethodInfo *minfo)
59 load_symfile (MonoSymbolFile *symfile)
61 MonoSymbolFilePriv *priv = symfile->_priv;
62 MonoSymbolFileMethodEntry *me;
63 const char *ptr, *start;
68 ptr = start = symfile->raw_contents;
70 magic = *((guint64 *) ptr)++;
71 if (magic != MONO_SYMBOL_FILE_MAGIC) {
72 g_warning ("Symbol file %s has is not a mono symbol file", priv->file_name);
76 version = *((guint32 *) ptr)++;
77 if (version != MONO_SYMBOL_FILE_VERSION) {
78 g_warning ("Symbol file %s has incorrect line number table version "
79 "(expected %d, got %ld)", priv->file_name,
80 MONO_SYMBOL_FILE_VERSION, version);
84 priv->offset_table = (MonoSymbolFileOffsetTable *) ptr;
91 priv->method_table = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
92 (GDestroyNotify) g_free);
93 priv->method_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
94 (GDestroyNotify) free_method_info);
96 ptr = symfile->raw_contents + priv->offset_table->method_table_offset;
97 me = (MonoSymbolFileMethodEntry *) ptr;
99 for (i = 0; i < priv->offset_table->method_count; i++, me++) {
100 MonoMethod *method = mono_get_method (priv->image, me->token, NULL);
101 MonoSymbolFileMethodEntryPriv *mep;
102 MonoDebugMethodInfo *minfo;
107 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
108 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
109 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
110 g_assert_not_reached ();
112 if (!((MonoMethodNormal *) method)->header) {
113 g_warning (G_STRLOC ": Internal error: method %s.%s doesn't have a header",
114 method->klass->name, method->name);
118 minfo = g_new0 (MonoDebugMethodInfo, 1);
119 minfo->file_offset = ((const char *) me) - start;
120 minfo->method = method;
121 minfo->symfile = symfile;
122 minfo->num_il_offsets = me->num_line_numbers;
123 minfo->il_offsets = (MonoSymbolFileLineNumberEntry *)
124 (symfile->raw_contents + me->line_number_table_offset);
126 mep = g_new0 (MonoSymbolFileMethodEntryPriv, 1);
127 mep->method = method;
132 mep->method_name_offset = priv->string_table_size;
133 mep->name = g_strdup_printf ("%s%s.%s", method->klass->name_space,
134 method->klass->name, method->name);
135 priv->string_table_size += strlen (mep->name) + 1;
137 g_hash_table_insert (priv->method_table, method, mep);
138 g_hash_table_insert (priv->method_hash, method, minfo);
141 if (!write_string_table (symfile))
148 mono_debug_open_mono_symbol_file (MonoImage *image, const char *filename, gboolean emit_warnings)
150 MonoSymbolFile *symfile;
151 MonoSymbolFilePriv *priv;
156 fd = open (filename, O_RDONLY);
159 g_warning ("Can't open symbol file: %s", filename);
163 file_size = lseek (fd, 0, SEEK_END);
164 lseek (fd, 0, SEEK_SET);
166 if (file_size == (off_t) -1) {
168 g_warning ("Can't get size of symbol file: %s", filename);
172 ptr = mono_raw_buffer_load (fd, FALSE, 0, file_size);
175 g_warning ("Can't read symbol file: %s", filename);
179 symfile = g_new0 (MonoSymbolFile, 1);
180 symfile->magic = MONO_SYMBOL_FILE_MAGIC;
181 symfile->version = MONO_SYMBOL_FILE_VERSION;
182 symfile->dynamic_magic = MONO_SYMBOL_FILE_DYNAMIC_MAGIC;
183 symfile->dynamic_version = MONO_SYMBOL_FILE_DYNAMIC_VERSION;
184 symfile->image_file = g_strdup (image->name);
185 symfile->symbol_file = g_strdup (filename);
186 symfile->raw_contents = ptr;
187 symfile->raw_contents_size = file_size;
189 symfile->_priv = priv = g_new0 (MonoSymbolFilePriv, 1);
193 priv->file_name = g_strdup (filename);
195 if (!load_symfile (symfile)) {
196 mono_debug_close_mono_symbol_file (symfile);
204 close_symfile (MonoSymbolFile *symfile)
206 MonoSymbolFilePriv *priv = symfile->_priv;
208 if (symfile->raw_contents) {
209 mono_raw_buffer_free (symfile->raw_contents);
210 symfile->raw_contents = NULL;
218 if (priv->method_table) {
219 g_hash_table_destroy (priv->method_table);
220 priv->method_table = NULL;
223 if (priv->method_hash) {
224 g_hash_table_destroy (priv->method_hash);
225 priv->method_hash = NULL;
228 if (symfile->is_dynamic)
229 unlink (priv->file_name);
231 if (symfile->image_file) {
232 g_free (symfile->image_file);
233 symfile->image_file = NULL;
236 if (priv->file_name) {
237 g_free (priv->file_name);
238 priv->file_name = NULL;
245 mono_debug_close_mono_symbol_file (MonoSymbolFile *symfile)
250 close_symfile (symfile);
252 g_free (symfile->_priv->source_file);
253 g_free (symfile->_priv);
254 g_free (symfile->image_file);
255 g_free (symfile->symbol_file);
260 write_string (int fd, const char *string)
262 guint32 length = strlen (string);
264 if (write (fd, &length, sizeof (length)) < 0)
267 if (write (fd, string, strlen (string)) < 0)
274 read_string (const char *ptr)
276 int len = *((guint32 *) ptr)++;
278 return g_filename_from_utf8 (ptr, len, NULL, NULL, NULL);
282 mono_debug_find_source_location (MonoSymbolFile *symfile, MonoMethod *method, guint32 offset,
283 guint32 *line_number)
285 MonoSymbolFilePriv *priv = symfile->_priv;
286 MonoSymbolFileLineNumberEntry *lne;
287 MonoSymbolFileMethodEntryPriv *mep;
288 gchar *source_file = NULL;
292 if (!priv->method_table || symfile->is_dynamic)
295 mep = g_hash_table_lookup (priv->method_table, method);
299 if (mep->entry->source_file_offset)
300 source_file = read_string (symfile->raw_contents + mep->entry->source_file_offset);
302 ptr = symfile->raw_contents + mep->entry->line_number_table_offset;
304 lne = (MonoSymbolFileLineNumberEntry *) ptr;
306 for (i = 0; i < mep->entry->num_line_numbers; i++, lne++) {
307 if (lne->offset < offset)
311 *line_number = lne->row;
316 } else if (source_file) {
317 gchar *retval = g_strdup_printf ("%s:%d", source_file, lne->row);
318 g_free (source_file);
321 return g_strdup_printf ("%d", lne->row);
328 mono_debug_symfile_add_method (MonoSymbolFile *symfile, MonoMethod *method)
330 MonoSymbolFileMethodEntryPriv *mep;
331 MonoSymbolFileMethodAddress *address;
332 MonoDebugVarInfo *var_table;
333 MonoSymbolFileLineNumberEntry *lne;
334 MonoDebugRangeInfo *range;
335 guint32 size, line_size, line_offset, num_variables, variable_size, variable_offset;
336 guint32 type_size, type_offset, *line_addresses, *type_index_table;
337 gpointer *type_table;
341 mep = g_hash_table_lookup (symfile->_priv->method_table, method);
346 mep->minfo = g_hash_table_lookup (symfile->_priv->method_hash, mep->method);
351 if (!mep->minfo->jit)
354 symfile->generation++;
356 size = sizeof (MonoSymbolFileMethodAddress);
358 line_size = mep->entry->num_line_numbers * sizeof (MonoSymbolFileLineNumberEntry);
362 num_variables = mep->entry->num_parameters + mep->entry->num_locals;
363 if (mep->entry->this_type_index)
366 variable_size = num_variables * sizeof (MonoDebugVarInfo);
367 variable_offset = size;
368 size += variable_size;
370 type_size = num_variables * sizeof (gpointer);
374 address = g_malloc0 (size);
375 ptr = (guint8 *) address;
377 address->size = size;
378 address->start_address = GPOINTER_TO_UINT (mep->minfo->jit->code_start);
379 address->end_address = GPOINTER_TO_UINT (mep->minfo->jit->code_start + mep->minfo->jit->code_size);
380 address->line_table_offset = line_offset;
381 address->variable_table_offset = variable_offset;
382 address->type_table_offset = type_offset;
384 range = allocate_range_entry (symfile);
385 range->file_offset = mep->minfo->file_offset;
386 range->start_address = address->start_address;
387 range->end_address = address->end_address;
388 range->dynamic_data = address;
389 range->dynamic_size = size;
391 var_table = (MonoDebugVarInfo *) (ptr + variable_offset);
392 type_table = (gpointer *) (ptr + type_offset);
394 type_index_table = (guint32 *)
395 (symfile->raw_contents + mep->entry->type_index_table_offset);
397 if (mep->entry->this_type_index) {
398 if (!mep->minfo->jit->this_var) {
399 g_warning (G_STRLOC ": Method %s.%s doesn't have `this'.",
400 mep->method->klass->name, mep->method->name);
403 *var_table++ = *mep->minfo->jit->this_var;
404 *type_table++ = write_type (symfile, &method->klass->this_arg);
408 if (mep->minfo->jit->num_params != mep->entry->num_parameters) {
409 g_warning (G_STRLOC ": Method %s.%s has %d parameters, but symbol file claims it has %d.",
410 mep->method->klass->name, mep->method->name, mep->minfo->jit->num_params,
411 mep->entry->num_parameters);
412 var_table += mep->entry->num_parameters;
414 for (i = 0; i < mep->minfo->jit->num_params; i++) {
415 *var_table++ = mep->minfo->jit->params [i];
416 *type_table++ = write_type (symfile, method->signature->params [i]);
420 if (mep->minfo->jit->num_locals != mep->entry->num_locals) {
422 g_warning (G_STRLOC ": Method %s.%s has %d locals, but symbol file claims it has %d.",
423 mep->method->klass->name, mep->method->name, mep->minfo->jit->num_locals,
424 mep->entry->num_locals);
426 var_table += mep->entry->num_locals;
428 for (i = 0; i < mep->minfo->jit->num_locals; i++)
429 *var_table++ = mep->minfo->jit->locals [i];
431 lne = (MonoSymbolFileLineNumberEntry *)
432 (symfile->raw_contents + mep->entry->line_number_table_offset);
434 line_addresses = (guint32 *) (ptr + line_offset);
436 for (i = 0; i < mep->entry->num_line_numbers; i++, lne++) {
440 line_addresses [i] = 0;
442 } else if (lne->offset == 0) {
443 line_addresses [i] = mep->minfo->jit->prologue_end;
447 line_addresses [i] = mep->minfo->jit->code_size;
449 for (j = 0; j < mep->minfo->num_il_offsets; j++) {
450 MonoSymbolFileLineNumberEntry *il = &mep->minfo->il_offsets [j];
452 if (il->offset >= lne->offset) {
453 line_addresses [i] = mep->minfo->jit->il_addresses [j];
461 free_method_entry (MonoSymbolFileMethodEntryPriv *mep)
469 create_method (MonoSymbolFile *symfile, guint32 token, MonoMethod *method)
471 MonoSymbolFileMethodEntryPriv *mep;
472 MonoDebugMethodInfo *minfo;
474 g_assert (method->klass->image == symfile->_priv->image);
476 mep = g_new0 (MonoSymbolFileMethodEntryPriv, 1);
477 mep->entry = g_new0 (MonoSymbolFileMethodEntry, 1);
478 mep->entry->token = token;
479 mep->entry->source_file_offset = symfile->_priv->offset_table->source_table_offset;
481 mep->method_name_offset = symfile->_priv->string_table_size;
482 mep->name = g_strdup_printf ("%s%s.%s", method->klass->name_space,
483 method->klass->name, method->name);
484 symfile->_priv->string_table_size += strlen (mep->name) + 1;
486 minfo = g_new0 (MonoDebugMethodInfo, 1);
487 minfo->method = method;
488 minfo->symfile = symfile;
491 mep->method = method;
493 symfile->_priv->offset_table->method_count++;
495 g_hash_table_insert (symfile->_priv->method_table, method, mep);
496 g_hash_table_insert (symfile->_priv->method_hash, method, minfo);
500 write_method (gpointer key, gpointer value, gpointer user_data)
502 MonoSymbolFile *symfile = (MonoSymbolFile *) user_data;
503 MonoSymbolFileMethodEntryPriv *mep = (MonoSymbolFileMethodEntryPriv *) value;
505 if (symfile->_priv->error)
508 mep->minfo->file_offset = lseek (symfile->_priv->fd, 0, SEEK_CUR);
510 if (write (symfile->_priv->fd, mep->entry, sizeof (MonoSymbolFileMethodEntry)) < 0) {
511 symfile->_priv->error = TRUE;
517 write_line_numbers (gpointer key, gpointer value, gpointer user_data)
519 MonoSymbolFile *symfile = (MonoSymbolFile *) user_data;
520 MonoSymbolFilePriv *priv = symfile->_priv;
521 MonoSymbolFileMethodEntryPriv *mep = (MonoSymbolFileMethodEntryPriv *) value;
522 MonoSymbolFileLineNumberEntry lne;
523 const unsigned char *ip, *start, *end;
524 MonoMethodHeader *header;
529 if ((mep->method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
530 (mep->method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
531 (mep->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
532 g_assert_not_reached ();
534 header = ((MonoMethodNormal *) mep->method)->header;
537 mep->entry->line_number_table_offset = lseek (priv->fd, 0, SEEK_CUR);
538 ++mep->entry->num_line_numbers;
543 if (write (priv->fd, &lne, sizeof (MonoSymbolFileLineNumberEntry)) < 0) {
548 ip = start = header->code;
549 end = ip + header->code_size;
554 ++mep->entry->num_line_numbers;
555 lne.offset = ip - start;
558 if (write (priv->fd, &lne, sizeof (MonoSymbolFileLineNumberEntry)) < 0) {
563 line = mono_disasm_code_one (NULL, mep->method, ip, &ip);
569 create_methods (MonoSymbolFile *symfile)
571 MonoImage *image = symfile->_priv->image;
572 MonoTableInfo *table = &image->tables [MONO_TABLE_METHOD];
575 for (idx = 1; idx <= table->rows; idx++) {
576 guint32 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
577 MonoMethod *method = mono_get_method (image, token, NULL);
579 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
580 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
581 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
584 if (method->wrapper_type != MONO_WRAPPER_NONE)
587 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
588 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
589 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
590 g_assert_not_reached ();
592 if (!((MonoMethodNormal *) method)->header) {
593 g_warning (G_STRLOC ": Internal error: method %s.%s doesn't have a header",
594 method->klass->name, method->name);
598 create_method (symfile, token, method);
603 load_line_numbers (gpointer key, gpointer value, gpointer user_data)
605 MonoSymbolFile *symfile = (MonoSymbolFile *) user_data;
606 MonoSymbolFileMethodEntryPriv *mep = (MonoSymbolFileMethodEntryPriv *) value;
608 mep->minfo->num_il_offsets = mep->entry->num_line_numbers;
609 mep->minfo->il_offsets = (MonoSymbolFileLineNumberEntry *)
610 (symfile->raw_contents + mep->entry->line_number_table_offset);
614 create_symfile (MonoSymbolFile *symfile, gboolean emit_warnings)
616 MonoSymbolFilePriv *priv = symfile->_priv;
622 priv->fd = g_file_open_tmp (NULL, &priv->file_name, NULL);
623 if (priv->fd == -1) {
625 g_warning ("Can't create symbol file");
629 symfile->symbol_file = g_strdup (priv->file_name);
631 magic = MONO_SYMBOL_FILE_MAGIC;
632 if (write (priv->fd, &magic, sizeof (magic)) < 0)
635 version = MONO_SYMBOL_FILE_VERSION;
636 if (write (priv->fd, &version, sizeof (version)) < 0)
639 offset = lseek (priv->fd, 0, SEEK_CUR);
641 priv->offset_table = g_new0 (MonoSymbolFileOffsetTable, 1);
642 if (write (priv->fd, priv->offset_table, sizeof (MonoSymbolFileOffsetTable)) < 0)
646 // Write source file table.
648 if (priv->source_file) {
649 priv->offset_table->source_table_offset = lseek (priv->fd, 0, SEEK_CUR);
650 if (!write_string (priv->fd, priv->source_file))
652 priv->offset_table->source_table_size = lseek (priv->fd, 0, SEEK_CUR) -
653 priv->offset_table->source_table_offset;
657 // Create method table.
660 priv->method_table = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
661 (GDestroyNotify) free_method_entry);
662 priv->method_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
663 (GDestroyNotify) free_method_info);
665 create_methods (symfile);
668 // Write line numbers.
671 priv->offset_table->line_number_table_offset = lseek (priv->fd, 0, SEEK_CUR);
673 g_hash_table_foreach (priv->method_table, write_line_numbers, symfile);
677 priv->offset_table->line_number_table_size = lseek (priv->fd, 0, SEEK_CUR) -
678 priv->offset_table->line_number_table_offset;
681 // Write method table.
684 priv->offset_table->method_table_offset = lseek (priv->fd, 0, SEEK_CUR);
686 g_hash_table_foreach (priv->method_table, write_method, symfile);
690 priv->offset_table->method_table_size = lseek (priv->fd, 0, SEEK_CUR) -
691 priv->offset_table->method_table_offset;
694 // Write offset table.
697 symfile->raw_contents_size = lseek (priv->fd, 0, SEEK_CUR);
699 lseek (priv->fd, offset, SEEK_SET);
700 if (write (priv->fd, priv->offset_table, sizeof (MonoSymbolFileOffsetTable)) < 0)
703 lseek (priv->fd, symfile->raw_contents_size, SEEK_SET);
705 ptr = mono_raw_buffer_load (priv->fd, TRUE, 0, symfile->raw_contents_size);
709 symfile->raw_contents = ptr;
712 // Load line number table.
714 g_hash_table_foreach (priv->method_table, load_line_numbers, symfile);
718 if (!write_string_table (symfile))
725 mono_debug_create_mono_symbol_file (MonoImage *image)
727 MonoSymbolFile *symfile;
729 symfile = g_new0 (MonoSymbolFile, 1);
730 symfile->magic = MONO_SYMBOL_FILE_MAGIC;
731 symfile->version = MONO_SYMBOL_FILE_VERSION;
732 symfile->dynamic_magic = MONO_SYMBOL_FILE_DYNAMIC_MAGIC;
733 symfile->dynamic_version = MONO_SYMBOL_FILE_DYNAMIC_VERSION;
734 symfile->is_dynamic = TRUE;
735 symfile->image_file = g_strdup (image->name);
737 symfile->_priv = g_new0 (MonoSymbolFilePriv, 1);
738 symfile->_priv->image = image;
740 if (!create_symfile (symfile, TRUE)) {
741 mono_debug_close_mono_symbol_file (symfile);
748 MonoDebugMethodInfo *
749 mono_debug_find_method (MonoSymbolFile *symfile, MonoMethod *method)
751 return g_hash_table_lookup (symfile->_priv->method_hash, method);
755 write_method_name (gpointer key, gpointer value, gpointer user_data)
757 MonoSymbolFile *symfile = (MonoSymbolFile *) user_data;
758 MonoSymbolFileMethodEntryPriv *mep = (MonoSymbolFileMethodEntryPriv *) value;
759 MonoSymbolFilePriv *priv = symfile->_priv;
760 guint8 *offset_ptr, *string_ptr;
763 offset = mep->method_name_offset + priv->string_offset_size;
765 offset_ptr = symfile->string_table + mep->index * 4;
766 string_ptr = symfile->string_table + offset;
768 *((guint32 *) offset_ptr) = offset;
769 strcpy (string_ptr, mep->name);
773 write_string_table (MonoSymbolFile *symfile)
775 MonoSymbolFilePriv *priv = symfile->_priv;
777 priv->string_offset_size = priv->offset_table->method_count * 4;
779 symfile->string_table_size = priv->string_table_size + priv->string_offset_size;
780 symfile->string_table = g_malloc0 (symfile->string_table_size);
782 g_hash_table_foreach (symfile->_priv->method_table, write_method_name, symfile);
786 MonoReflectionMethod *
787 ves_icall_MonoDebugger_GetMethod (MonoReflectionAssembly *assembly, guint32 token)
791 method = mono_get_method (assembly->assembly->image, token, NULL);
793 return mono_method_get_object (mono_domain_get (), method, NULL);
797 ves_icall_MonoDebugger_GetLocalTypeFromSignature (MonoReflectionAssembly *assembly, MonoArray *signature)
805 MONO_CHECK_ARG_NULL (assembly);
806 MONO_CHECK_ARG_NULL (signature);
808 domain = mono_domain_get();
809 image = assembly->assembly->image;
811 ptr = mono_array_addr (signature, char, 0);
812 g_assert (*ptr++ == 0x07);
813 len = mono_metadata_decode_value (ptr, &ptr);
816 type = mono_metadata_parse_type (image, MONO_PARSE_LOCAL, 0, ptr, &ptr);
818 return mono_type_get_object (domain, type);
821 static MonoDebugRangeInfo *
822 allocate_range_entry (MonoSymbolFile *symfile)
824 MonoDebugRangeInfo *retval;
825 guint32 size, chunks;
827 symfile->range_entry_size = sizeof (MonoDebugRangeInfo);
829 if (!symfile->range_table) {
830 size = sizeof (MonoDebugRangeInfo) * RANGE_TABLE_CHUNK_SIZE;
831 symfile->range_table = g_malloc0 (size);
832 symfile->num_range_entries = 1;
833 return symfile->range_table;
836 if (!((symfile->num_range_entries + 1) % RANGE_TABLE_CHUNK_SIZE)) {
837 chunks = (symfile->num_range_entries + 1) / RANGE_TABLE_CHUNK_SIZE;
838 size = sizeof (MonoDebugRangeInfo) * RANGE_TABLE_CHUNK_SIZE * (chunks + 1);
840 symfile->range_table = g_realloc (symfile->range_table, size);
843 retval = symfile->range_table + symfile->num_range_entries;
844 symfile->num_range_entries++;
849 write_type (MonoSymbolFile *symfile, MonoType *type)
851 guint8 buffer [BUFSIZ], *ptr = buffer, *retval;
855 type_table = g_hash_table_new (g_direct_hash, g_direct_equal);
857 retval = g_hash_table_lookup (type_table, type);
861 switch (type->type) {
862 case MONO_TYPE_BOOLEAN:
865 *((int *) ptr)++ = 1;
871 *((int *) ptr)++ = 2;
877 *((int *) ptr)++ = 4;
883 *((int *) ptr)++ = 8;
886 case MONO_TYPE_STRING: {
889 *((int *) ptr)++ = -8;
890 *((guint32 *) ptr)++ = sizeof (MonoString);
892 *ptr++ = (guint8*)&string.length - (guint8*)&string;
893 *ptr++ = sizeof (string.length);
894 *ptr++ = (guint8*)&string.chars - (guint8*)&string;
898 case MONO_TYPE_SZARRAY: {
901 *((int *) ptr)++ = -8 - sizeof (gpointer);
902 *((guint32 *) ptr)++ = sizeof (MonoArray);
904 *ptr++ = (guint8*)&array.max_length - (guint8*)&array;
905 *ptr++ = sizeof (array.max_length);
906 *ptr++ = (guint8*)&array.vector - (guint8*)&array;
907 *((gpointer *) ptr)++ = write_type (symfile, type->data.type);
911 case MONO_TYPE_ARRAY: {
913 MonoArrayBounds bounds;
915 *((int *) ptr)++ = -15 - sizeof (gpointer);
916 *((guint32 *) ptr)++ = sizeof (MonoArray);
918 *ptr++ = (guint8*)&array.max_length - (guint8*)&array;
919 *ptr++ = sizeof (array.max_length);
920 *ptr++ = (guint8*)&array.vector - (guint8*)&array;
921 *ptr++ = type->data.array->rank;
922 *ptr++ = (guint8*)&array.bounds - (guint8*)&array;
923 *ptr++ = sizeof (MonoArrayBounds);
924 *ptr++ = (guint8*)&bounds.lower_bound - (guint8*)&bounds;
925 *ptr++ = sizeof (bounds.lower_bound);
926 *ptr++ = (guint8*)&bounds.length - (guint8*)&bounds;
927 *ptr++ = sizeof (bounds.length);
928 *((gpointer *) ptr)++ = write_type (symfile, type->data.array->type);
932 case MONO_TYPE_VALUETYPE:
933 case MONO_TYPE_CLASS: {
934 MonoClass *klass = type->data.klass;
936 mono_class_init (klass);
937 if (klass->enumtype) {
938 *((int *) ptr)++ = -5 - sizeof (gpointer);
939 *((guint32 *) ptr)++ = sizeof (MonoObject);
941 *((gpointer *) ptr)++ = write_type (symfile, klass->enum_basetype);
945 *((int *) ptr)++ = -4;
946 *((guint32 *) ptr)++ = klass->instance_size;
952 g_message (G_STRLOC ": %p - %x,%x,%x", type, type->attrs, type->type, type->byref);
954 *((int *) ptr)++ = -1;
960 retval = g_malloc0 (size + 4);
961 memcpy (retval + 4, buffer, size);
962 *((int *) retval) = size;
964 g_hash_table_insert (type_table, type, retval);