copying the latest Sys.Web.Services from trunk.
[mono.git] / mono / metadata / mono-debug.c
1 #include <config.h>
2 #include <mono/metadata/assembly.h>
3 #include <mono/metadata/tabledefs.h>
4 #include <mono/metadata/tokentype.h>
5 #include <mono/metadata/appdomain.h>
6 #include <mono/metadata/class-internals.h>
7 #include <mono/metadata/mono-debug.h>
8 #include <mono/metadata/mono-debug-debugger.h>
9 #include <mono/metadata/mono-endian.h>
10 #include <string.h>
11
12 #define SYMFILE_TABLE_CHUNK_SIZE        16
13 #define DATA_TABLE_PTR_CHUNK_SIZE       256
14 #define DATA_TABLE_CHUNK_SIZE           32768
15
16 MonoSymbolTable *mono_symbol_table = NULL;
17 MonoDebugFormat mono_debug_format = MONO_DEBUG_FORMAT_NONE;
18
19 static gboolean in_the_mono_debugger = FALSE;
20 static gboolean mono_debug_initialized = FALSE;
21 GHashTable *mono_debug_handles = NULL;
22
23 static GHashTable *method_hash = NULL;
24
25 static MonoDebugHandle     *mono_debug_open_image      (MonoImage *image);
26 static void                 mono_debug_close_image     (MonoDebugHandle *debug);
27
28 static MonoDebugHandle     *_mono_debug_get_image      (MonoImage *image);
29 static void                 mono_debug_add_assembly    (MonoAssembly *assembly,
30                                                         gpointer user_data);
31 static void                 mono_debug_start_add_type  (MonoClass *klass);
32 static void                 mono_debug_add_type        (MonoClass *klass);
33
34 extern void (*mono_debugger_class_init_func) (MonoClass *klass);
35 extern void (*mono_debugger_start_class_init_func) (MonoClass *klass);
36
37 typedef struct {
38         guint32 symfile_id;
39         guint32 domain_id;
40         guint32 method_id;
41 } MethodHashEntry;
42
43 static guint
44 method_hash_hash (gconstpointer data)
45 {
46         const MethodHashEntry *entry = (const MethodHashEntry *) data;
47         return entry->symfile_id | (entry->domain_id << 16);
48 }
49
50 static gint
51 method_hash_equal (gconstpointer ka, gconstpointer kb)
52 {
53         const MethodHashEntry *a = (const MethodHashEntry *) ka;
54         const MethodHashEntry *b = (const MethodHashEntry *) kb;
55
56         if ((a->symfile_id != b->symfile_id) || (a->method_id != b->method_id) || (a->domain_id != b->domain_id))
57                 return 0;
58         return 1;
59 }
60
61 /*
62  * Initialize debugging support.
63  *
64  * This method must be called after loading corlib,
65  * but before opening the application's main assembly because we need to set some
66  * callbacks here.
67  */
68 void
69 mono_debug_init (MonoDebugFormat format)
70 {
71         g_assert (!mono_debug_initialized);
72
73         mono_debug_initialized = TRUE;
74         mono_debug_format = format;
75         in_the_mono_debugger = format == MONO_DEBUG_FORMAT_DEBUGGER;
76
77         if (in_the_mono_debugger)
78                 mono_debugger_initialize ();
79
80         mono_debugger_lock ();
81
82         mono_symbol_table = g_new0 (MonoSymbolTable, 1);
83         mono_symbol_table->magic = MONO_DEBUGGER_MAGIC;
84         mono_symbol_table->version = MONO_DEBUGGER_VERSION;
85         mono_symbol_table->total_size = sizeof (MonoSymbolTable);
86
87         mono_debug_handles = g_hash_table_new_full
88                 (NULL, NULL, NULL, (GDestroyNotify) mono_debug_close_image);
89         method_hash = g_hash_table_new (method_hash_hash, method_hash_equal);
90
91         mono_debugger_start_class_init_func = mono_debug_start_add_type;
92         mono_debugger_class_init_func = mono_debug_add_type;
93         mono_install_assembly_load_hook (mono_debug_add_assembly, NULL);
94 }
95
96 void
97 mono_debug_init_1 (MonoDomain *domain)
98 {
99         MonoDebugHandle *handle = mono_debug_open_image (mono_get_corlib ());
100
101         if (in_the_mono_debugger)
102                 mono_debugger_add_builtin_types (handle);
103 }
104
105 /*
106  * Initialize debugging support - part 2.
107  *
108  * This method must be called after loading the application's main assembly.
109  */
110 void
111 mono_debug_init_2 (MonoAssembly *assembly)
112 {
113         mono_debug_open_image (mono_assembly_get_image (assembly));
114 }
115
116 void
117 mono_debug_cleanup (void)
118 {
119         mono_debugger_cleanup ();
120
121         if (mono_debug_handles)
122                 g_hash_table_destroy (mono_debug_handles);
123         mono_debug_handles = NULL;
124 }
125
126 static MonoDebugHandle *
127 _mono_debug_get_image (MonoImage *image)
128 {
129         return g_hash_table_lookup (mono_debug_handles, image);
130 }
131
132 static MonoDebugHandle *
133 allocate_debug_handle (MonoSymbolTable *table)
134 {
135         MonoDebugHandle *handle;
136
137         if (!table->symbol_files)
138                 table->symbol_files = g_new0 (MonoDebugHandle *, SYMFILE_TABLE_CHUNK_SIZE);
139         else if (!((table->num_symbol_files + 1) % SYMFILE_TABLE_CHUNK_SIZE)) {
140                 guint32 chunks = (table->num_symbol_files + 1) / SYMFILE_TABLE_CHUNK_SIZE;
141                 guint32 size = sizeof (MonoDebugHandle *) * SYMFILE_TABLE_CHUNK_SIZE * (chunks + 1);
142
143                 table->symbol_files = g_realloc (table->symbol_files, size);
144         }
145
146         handle = g_new0 (MonoDebugHandle, 1);
147         handle->index = table->num_symbol_files;
148         table->symbol_files [table->num_symbol_files++] = handle;
149         return handle;
150 }
151
152 static MonoDebugHandle *
153 mono_debug_open_image (MonoImage *image)
154 {
155         MonoDebugHandle *handle;
156
157         if (mono_image_is_dynamic (image))
158                 return NULL;
159
160         handle = _mono_debug_get_image (image);
161         if (handle != NULL)
162                 return handle;
163
164         handle = allocate_debug_handle (mono_symbol_table);
165
166         handle->image = image;
167         mono_image_addref (image);
168         handle->image_file = g_strdup (mono_image_get_filename (image));
169
170         g_hash_table_insert (mono_debug_handles, image, handle);
171
172         handle->symfile = mono_debug_open_mono_symbol_file (handle, in_the_mono_debugger);
173         if (in_the_mono_debugger)
174                 mono_debugger_add_symbol_file (handle);
175
176         return handle;
177 }
178
179 static void
180 mono_debug_close_image (MonoDebugHandle *handle)
181 {
182         if (handle->symfile)
183                 mono_debug_close_mono_symbol_file (handle->symfile);
184         /* decrease the refcount added with mono_image_addref () */
185         mono_image_close (handle->image);
186         g_free (handle->image_file);
187         g_free (handle->_priv);
188         g_free (handle);
189 }
190
191 static void
192 mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data)
193 {
194         mono_debugger_lock ();
195         mono_debug_open_image (mono_assembly_get_image (assembly));
196         mono_debugger_unlock ();
197 }
198
199 /*
200  * Allocate a new data item of size `size'.
201  * Returns the global offset which is to be used to reference this data item and
202  * a pointer (in the `ptr' argument) which is to be used to write it.
203  */
204 static guint8 *
205 allocate_data_item (MonoDebugDataItemType type, guint32 size)
206 {
207         guint32 chunk_size;
208         guint8 *data;
209
210         g_assert (mono_symbol_table);
211
212         if (size + 12 < DATA_TABLE_CHUNK_SIZE)
213                 chunk_size = DATA_TABLE_CHUNK_SIZE;
214         else
215                 chunk_size = size + 12;
216
217         /* Initialize things if necessary. */
218         if (!mono_symbol_table->current_data_table) {
219                 mono_symbol_table->current_data_table = g_malloc0 (chunk_size);
220                 mono_symbol_table->current_data_table_size = chunk_size;
221                 mono_symbol_table->current_data_table_offset = 4;
222
223                 * ((guint32 *) mono_symbol_table->current_data_table) = chunk_size;
224         }
225
226  again:
227         /* First let's check whether there's still enough room in the current_data_table. */
228         if (mono_symbol_table->current_data_table_offset + size + 8 < mono_symbol_table->current_data_table_size) {
229                 data = ((guint8 *) mono_symbol_table->current_data_table) + mono_symbol_table->current_data_table_offset;
230                 mono_symbol_table->current_data_table_offset += size + 8;
231
232                 * ((guint32 *) data) = size;
233                 data += 4;
234                 * ((guint32 *) data) = type;
235                 data += 4;
236                 return data;
237         }
238
239         /* Add the current_data_table to the data_tables vector and ... */
240         if (!mono_symbol_table->data_tables) {
241                 guint32 tsize = sizeof (gpointer) * DATA_TABLE_PTR_CHUNK_SIZE;
242                 mono_symbol_table->data_tables = g_malloc0 (tsize);
243         }
244
245         if (!((mono_symbol_table->num_data_tables + 1) % DATA_TABLE_PTR_CHUNK_SIZE)) {
246                 guint32 chunks = (mono_symbol_table->num_data_tables + 1) / DATA_TABLE_PTR_CHUNK_SIZE;
247                 guint32 tsize = sizeof (gpointer) * DATA_TABLE_PTR_CHUNK_SIZE * (chunks + 1);
248
249                 mono_symbol_table->data_tables = g_realloc (mono_symbol_table->data_tables, tsize);
250         }
251
252         mono_symbol_table->data_tables [mono_symbol_table->num_data_tables++] = mono_symbol_table->current_data_table;
253
254         /* .... allocate a new current_data_table. */
255         mono_symbol_table->current_data_table = g_malloc0 (chunk_size);
256         mono_symbol_table->current_data_table_size = chunk_size;
257         mono_symbol_table->current_data_table_offset = 4;
258         * ((guint32 *) mono_symbol_table->current_data_table) = chunk_size;
259
260         goto again;
261 }
262
263 struct LookupMethodData
264 {
265         MonoDebugMethodInfo *minfo;
266         MonoMethod *method;
267 };
268
269 static void
270 lookup_method_func (gpointer key, gpointer value, gpointer user_data)
271 {
272         MonoDebugHandle *handle = (MonoDebugHandle *) value;
273         struct LookupMethodData *data = (struct LookupMethodData *) user_data;
274
275         if (data->minfo)
276                 return;
277
278         if (handle->symfile)
279                 data->minfo = mono_debug_find_method (handle, data->method);
280 }
281
282 static MonoDebugMethodInfo *
283 _mono_debug_lookup_method (MonoMethod *method)
284 {
285         struct LookupMethodData data;
286
287         data.minfo = NULL;
288         data.method = method;
289
290         if (!mono_debug_handles)
291                 return NULL;
292
293         g_hash_table_foreach (mono_debug_handles, lookup_method_func, &data);
294         return data.minfo;
295 }
296
297 static inline void
298 write_leb128 (guint32 value, guint8 *ptr, guint8 **rptr)
299 {
300         do {
301                 guint8 byte = value & 0x7f;
302                 value >>= 7;
303                 if (value)
304                         byte |= 0x80;
305                 *ptr++ = byte;
306         } while (value);
307
308         *rptr = ptr;
309 }
310
311 static inline void
312 write_sleb128 (gint32 value, guint8 *ptr, guint8 **rptr)
313 {
314         gboolean more = 1;
315
316         while (more) {
317                 guint8 byte = value & 0x7f;
318                 value >>= 7;
319
320                 if (((value == 0) && ((byte & 0x40) == 0)) || ((value == -1) && (byte & 0x40)))
321                         more = 0;
322                 else
323                         byte |= 0x80;
324                 *ptr++ = byte;
325         }
326
327         *rptr = ptr;
328 }
329
330 static void
331 write_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
332 {
333         write_leb128 (var->index, ptr, &ptr);
334         write_sleb128 (var->offset, ptr, &ptr);
335         write_leb128 (var->size, ptr, &ptr);
336         write_leb128 (var->begin_scope, ptr, &ptr);
337         write_leb128 (var->end_scope, ptr, &ptr);
338         *rptr = ptr;
339 }
340
341 /*
342  * This is called by the JIT to tell the debugging code about a newly
343  * compiled method.
344  */
345 MonoDebugMethodAddress *
346 mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDomain *domain)
347 {
348         MonoDebugMethodAddress *address;
349         char buffer [BUFSIZ];
350         guint8 *ptr, *oldptr;
351         guint32 i, size, total_size, max_size;
352         gint32 last_il_offset = 0, last_native_offset = 0;
353         MonoDebugHandle *handle;
354         MonoDebugMethodInfo *minfo;
355         MethodHashEntry *hash;
356
357         if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
358             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
359             (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
360             (method->flags & METHOD_ATTRIBUTE_ABSTRACT))
361                 return NULL;
362
363         if (method->wrapper_type != MONO_WRAPPER_NONE)
364                 return NULL;
365
366         mono_debugger_lock ();
367
368         handle = _mono_debug_get_image (method->klass->image);
369         if (!handle || !handle->symfile || !handle->symfile->offset_table) {
370                 mono_debugger_unlock ();
371                 return NULL;
372         }
373
374         minfo = _mono_debug_lookup_method (method);
375         if (!minfo) {
376                 mono_debugger_unlock ();
377                 return NULL;
378         }
379
380         max_size = 24 + 8 * jit->num_line_numbers + 16 * minfo->num_lexical_blocks + 20 * (1 + jit->num_params + jit->num_locals);
381         if (max_size > BUFSIZ)
382                 ptr = oldptr = g_malloc (max_size);
383         else
384                 ptr = oldptr = buffer;
385
386         write_leb128 (jit->prologue_end, ptr, &ptr);
387         write_leb128 (jit->epilogue_begin, ptr, &ptr);
388
389         write_leb128 (jit->num_line_numbers, ptr, &ptr);
390         for (i = 0; i < jit->num_line_numbers; i++) {
391                 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
392
393                 write_sleb128 (lne->il_offset - last_il_offset, ptr, &ptr);
394                 write_sleb128 (lne->native_offset - last_native_offset, ptr, &ptr);
395
396                 last_il_offset = lne->il_offset;
397                 last_native_offset = lne->native_offset;
398         }
399
400         jit->num_lexical_blocks = minfo->num_lexical_blocks;
401         jit->lexical_blocks = g_new0 (MonoDebugLexicalBlockEntry, jit->num_lexical_blocks);
402         for (i = 0; i < jit->num_lexical_blocks; i ++) {
403                 MonoDebugLexicalBlockEntry *jit_lbe = &jit->lexical_blocks [i];
404                 MonoSymbolFileLexicalBlockEntry *minfo_lbe = &minfo->lexical_blocks [i];
405
406                 jit_lbe->il_start_offset = minfo_lbe->_start_offset;
407                 jit_lbe->native_start_offset = _mono_debug_address_from_il_offset (jit, jit_lbe->il_start_offset);
408
409                 jit_lbe->il_end_offset = minfo_lbe->_end_offset;
410                 jit_lbe->native_end_offset = _mono_debug_address_from_il_offset (jit, jit_lbe->il_end_offset);
411         }
412
413         last_il_offset = 0;
414         last_native_offset = 0;
415         write_leb128 (jit->num_lexical_blocks, ptr, &ptr);
416         for (i = 0; i < jit->num_lexical_blocks; i++) {
417                 MonoDebugLexicalBlockEntry *lbe = &jit->lexical_blocks [i];
418
419                 write_sleb128 (lbe->il_start_offset - last_il_offset, ptr, &ptr);
420                 write_sleb128 (lbe->native_start_offset - last_native_offset, ptr, &ptr);
421
422                 last_il_offset = lbe->il_start_offset;
423                 last_native_offset = lbe->native_start_offset;
424
425                 write_sleb128 (lbe->il_end_offset - last_il_offset, ptr, &ptr);
426                 write_sleb128 (lbe->native_end_offset - last_native_offset, ptr, &ptr);
427
428                 last_il_offset = lbe->il_end_offset;
429                 last_native_offset = lbe->native_end_offset;
430         }
431
432         *ptr++ = jit->this_var ? 1 : 0;
433         if (jit->this_var)
434                 write_variable (jit->this_var, ptr, &ptr);
435
436         write_leb128 (jit->num_params, ptr, &ptr);
437         for (i = 0; i < jit->num_params; i++)
438                 write_variable (&jit->params [i], ptr, &ptr);
439
440         write_leb128 (jit->num_locals, ptr, &ptr);
441         for (i = 0; i < jit->num_locals; i++)
442                 write_variable (&jit->locals [i], ptr, &ptr);
443
444         size = ptr - oldptr;
445         g_assert (size < max_size);
446         total_size = size + sizeof (MonoDebugMethodAddress);
447
448         if (total_size + 9 >= DATA_TABLE_CHUNK_SIZE) {
449                 // FIXME: Maybe we should print a warning here.
450                 //        This should only happen for very big methods, for instance
451                 //        with more than 40.000 line numbers and more than 5.000
452                 //        local variables.
453                 return NULL;
454         }
455
456         address = (MonoDebugMethodAddress *) allocate_data_item (MONO_DEBUG_DATA_ITEM_METHOD, total_size);
457
458         address->size = total_size;
459         address->symfile_id = handle->index;
460         address->domain_id = mono_domain_get_id (domain);
461         address->method_id = minfo->index;
462         address->code_start = jit->code_start;
463         address->code_size = jit->code_size;
464         address->wrapper_addr = jit->wrapper_addr;
465
466         memcpy (&address->data, oldptr, size);
467
468         if (max_size > BUFSIZ)
469                 g_free (oldptr);
470
471         hash = g_new0 (MethodHashEntry, 1);
472         hash->symfile_id = address->symfile_id;
473         hash->domain_id = address->domain_id;
474         hash->method_id = address->method_id;
475
476         g_hash_table_insert (method_hash, hash, address);
477
478         if (in_the_mono_debugger)
479                 mono_debugger_add_method (jit);
480
481         mono_debugger_unlock ();
482
483         return address;
484 }
485
486 static inline guint32
487 read_leb128 (guint8 *ptr, guint8 **rptr)
488 {
489         guint32 result = 0, shift = 0;
490
491         while (TRUE) {
492                 guint8 byte = *ptr++;
493
494                 result |= (byte & 0x7f) << shift;
495                 if ((byte & 0x80) == 0)
496                         break;
497                 shift += 7;
498         }
499
500         *rptr = ptr;
501         return result;
502 }
503
504 static inline gint32
505 read_sleb128 (guint8 *ptr, guint8 **rptr)
506 {
507         gint32 result = 0;
508         guint32 shift = 0;
509
510         while (TRUE) {
511                 guint8 byte = *ptr++;
512
513                 result |= (byte & 0x7f) << shift;
514                 shift += 7;
515
516                 if (byte & 0x80)
517                         continue;
518
519                 if ((shift < 32) && (byte & 0x40))
520                         result |= - (1 << shift);
521                 break;
522         }
523
524         *rptr = ptr;
525         return result;
526 }
527
528 static void
529 read_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
530 {
531         var->index = read_leb128 (ptr, &ptr);
532         var->offset = read_sleb128 (ptr, &ptr);
533         var->size = read_leb128 (ptr, &ptr);
534         var->begin_scope = read_leb128 (ptr, &ptr);
535         var->end_scope = read_leb128 (ptr, &ptr);
536         *rptr = ptr;
537 }
538
539 MonoDebugMethodJitInfo *
540 mono_debug_read_method (MonoDebugMethodAddress *address)
541 {
542         MonoDebugMethodJitInfo *jit;
543         guint32 i, il_offset = 0, native_offset = 0;
544         guint8 *ptr;
545
546         if (address->jit)
547                 return address->jit;
548
549         jit = address->jit = g_new0 (MonoDebugMethodJitInfo, 1);
550         jit->code_start = address->code_start;
551         jit->code_size = address->code_size;
552         jit->wrapper_addr = address->wrapper_addr;
553
554         ptr = (guint8 *) &address->data;
555
556         jit->prologue_end = read_leb128 (ptr, &ptr);
557         jit->epilogue_begin = read_leb128 (ptr, &ptr);
558
559         jit->num_line_numbers = read_leb128 (ptr, &ptr);
560         jit->line_numbers = g_new0 (MonoDebugLineNumberEntry, jit->num_line_numbers);
561         for (i = 0; i < jit->num_line_numbers; i++) {
562                 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
563
564                 il_offset += read_sleb128 (ptr, &ptr);
565                 native_offset += read_sleb128 (ptr, &ptr);
566
567                 lne->il_offset = il_offset;
568                 lne->native_offset = native_offset;
569         }
570
571         il_offset = 0;
572         native_offset = 0;
573         jit->num_lexical_blocks = read_leb128 (ptr, &ptr);
574         jit->lexical_blocks = g_new0 (MonoDebugLexicalBlockEntry, jit->num_lexical_blocks);
575         for (i = 0; i < jit->num_lexical_blocks; i ++) {
576                 MonoDebugLexicalBlockEntry *lbe = &jit->lexical_blocks [i];
577
578                 il_offset += read_sleb128 (ptr, &ptr);
579                 native_offset += read_sleb128 (ptr, &ptr);
580
581                 lbe->il_start_offset = il_offset;
582                 lbe->native_start_offset = native_offset;
583
584                 il_offset += read_sleb128 (ptr, &ptr);
585                 native_offset += read_sleb128 (ptr, &ptr);
586
587                 lbe->il_end_offset = il_offset;
588                 lbe->native_end_offset = native_offset;
589         }
590
591         if (*ptr++) {
592                 jit->this_var = g_new0 (MonoDebugVarInfo, 1);
593                 read_variable (jit->this_var, ptr, &ptr);
594         }
595
596         jit->num_params = read_leb128 (ptr, &ptr);
597         jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
598         for (i = 0; i < jit->num_params; i++)
599                 read_variable (&jit->params [i], ptr, &ptr);
600
601         jit->num_locals = read_leb128 (ptr, &ptr);
602         jit->locals = g_new0 (MonoDebugVarInfo, jit->num_locals);
603         for (i = 0; i < jit->num_locals; i++)
604                 read_variable (&jit->locals [i], ptr, &ptr);
605
606         return jit;
607 }
608
609 void
610 mono_debug_free_method_jit_info (MonoDebugMethodJitInfo *jit)
611 {
612         if (jit->address)
613                 jit->address->jit = NULL;
614
615         g_free (jit->line_numbers);
616         g_free (jit->this_var);
617         g_free (jit->params);
618         g_free (jit->locals);
619         g_free (jit);
620 }
621
622 /*
623  * This is called via the `mono_debugger_class_init_func' from mono_class_init() each time
624  * a new class is initialized.
625  */
626 static void
627 mono_debug_start_add_type (MonoClass *klass)
628 {
629         MonoDebugHandle *handle;
630
631         handle = _mono_debug_get_image (klass->image);
632         if (!handle)
633                 return;
634
635         if (in_the_mono_debugger)
636                 mono_debugger_add_type (handle, klass);
637 }
638
639 static guint32
640 get_token (MonoClass *klass)
641 {
642         while (klass->rank)
643                 klass = klass->element_class;
644
645         return klass->type_token;
646 }
647
648 static void
649 mono_debug_add_type (MonoClass *klass)
650 {
651         MonoDebugHandle *handle;
652         MonoDebugClassEntry *entry;
653         char buffer [BUFSIZ];
654         guint8 *ptr, *oldptr;
655         guint32 token, size, total_size, max_size;
656         int base_offset = 0;
657
658         handle = _mono_debug_get_image (klass->image);
659         if (!handle)
660                 return;
661
662         if (klass->generic_class ||
663             (klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR))
664                 return;
665
666         max_size = 12 + sizeof (gpointer);
667         if (max_size > BUFSIZ)
668                 ptr = oldptr = g_malloc (max_size);
669         else
670                 ptr = oldptr = buffer;
671
672         token = get_token (klass);
673         if (!token)
674                 return;
675
676         if (klass->valuetype)
677                 base_offset = - (int)(sizeof (MonoObject));
678
679         write_leb128 (token, ptr, &ptr);
680         write_leb128 (klass->rank, ptr, &ptr);
681         write_leb128 (klass->instance_size + base_offset, ptr, &ptr);
682         * ((gpointer *) ptr) = klass;
683         ptr += sizeof (gpointer);
684
685         size = ptr - oldptr;
686         g_assert (size < max_size);
687         total_size = size + sizeof (MonoDebugClassEntry);
688
689         if (total_size + 9 >= DATA_TABLE_CHUNK_SIZE) {
690                 // FIXME: Maybe we should print a warning here.
691                 //        This should only happen for very big methods, for instance
692                 //        with more than 40.000 line numbers and more than 5.000
693                 //        local variables.
694                 return;
695         }
696
697         entry = (MonoDebugClassEntry *) allocate_data_item (MONO_DEBUG_DATA_ITEM_CLASS, total_size);
698
699         entry->size = total_size;
700         entry->symfile_id = handle->index;
701
702         memcpy (&entry->data, oldptr, size);
703
704         if (max_size > BUFSIZ)
705                 g_free (oldptr);
706
707         mono_debugger_start_add_type (handle, klass);
708 }
709
710 static MonoDebugMethodJitInfo *
711 find_method (MonoDebugMethodInfo *minfo, MonoDomain *domain)
712 {
713         MethodHashEntry lookup;
714         MonoDebugMethodAddress *address;
715
716         lookup.symfile_id = minfo->handle->index;
717         lookup.domain_id = mono_domain_get_id (domain);
718         lookup.method_id = minfo->index;
719
720         address = g_hash_table_lookup (method_hash, &lookup);
721         if (!address)
722                 return NULL;
723
724         return mono_debug_read_method (address);
725 }
726
727 static gint32
728 il_offset_from_address (MonoDebugMethodInfo *minfo, MonoDomain *domain, guint32 native_offset)
729 {
730         MonoDebugMethodJitInfo *jit;
731         int i;
732
733         jit = find_method (minfo, domain);
734         if (!jit || !jit->line_numbers)
735                 return -1;
736
737         for (i = jit->num_line_numbers - 1; i >= 0; i--) {
738                 MonoDebugLineNumberEntry lne = jit->line_numbers [i];
739
740                 if (lne.native_offset <= native_offset)
741                         return lne.il_offset;
742         }
743
744         return -1;
745 }
746
747 /**
748  * mono_debug_source_location_from_address:
749  * @method:
750  * @address:
751  * @line_number:
752  * @domain:
753  *
754  * Used by the exception code to get a source location from a machine address.
755  *
756  * Returns: a textual representation of the specified address which is suitable to be displayed to
757  * the user (for instance "/home/martin/monocvs/debugger/test/Y.cs:8").
758  *
759  * If the optional @line_number argument is not NULL, the line number is stored there and just the
760  * source file is returned (ie. it'd return "/home/martin/monocvs/debugger/test/Y.cs" and store the
761  * line number 8 in the variable pointed to by @line_number).
762  */
763 gchar *
764 mono_debug_source_location_from_address (MonoMethod *method, guint32 address, guint32 *line_number,
765                                          MonoDomain *domain)
766 {
767         MonoDebugMethodInfo *minfo;
768         char *res = NULL;
769         gint32 offset;
770
771         mono_loader_lock ();
772         minfo = _mono_debug_lookup_method (method);
773         if (!minfo || !minfo->handle || !minfo->handle->symfile || !minfo->handle->symfile->offset_table) {
774                 mono_loader_unlock ();
775                 return NULL;
776         }
777
778         offset = il_offset_from_address (minfo, domain, address);
779                 
780         if (offset >= 0)
781                 res = mono_debug_find_source_location (minfo->handle->symfile, method, offset, line_number);
782
783         mono_loader_unlock ();
784         return res;
785 }
786
787 /**
788  * mono_debug_source_location_from_il_offset:
789  * @method:
790  * @offset:
791  * @line_number:
792  *
793  * Used by the exception code to get a source location from an IL offset.
794  *
795  * Returns a textual representation of the specified address which is suitable to be displayed to
796  * the user (for instance "/home/martin/monocvs/debugger/test/Y.cs:8").
797  *
798  * If the optional @line_number argument is not NULL, the line number is stored there and just the
799  * source file is returned (ie. it'd return "/home/martin/monocvs/debugger/test/Y.cs" and store the
800  * line number 8 in the variable pointed to by @line_number).
801  */
802 gchar *
803 mono_debug_source_location_from_il_offset (MonoMethod *method, guint32 offset, guint32 *line_number)
804 {
805         char *res;
806         MonoDebugMethodInfo *minfo;
807
808         mono_loader_lock ();
809         minfo = _mono_debug_lookup_method (method);
810         if (!minfo || !minfo->handle || !minfo->handle->symfile) {
811                 mono_loader_unlock ();
812                 return NULL;
813         }
814
815         res = mono_debug_find_source_location (minfo->handle->symfile, method, offset, line_number);
816         mono_loader_unlock ();
817         return res;
818 }
819
820 /**
821  * mono_debug_il_offset_from_address:
822  * @method:
823  * @address:
824  * @domain:
825  *
826  * Returns: the IL offset corresponding to machine address @address which is an offset
827  * relative to the beginning of the method @method.
828  */
829 gint32
830 mono_debug_il_offset_from_address (MonoMethod *method, gint32 address, MonoDomain *domain)
831 {
832         MonoDebugMethodInfo *minfo;
833         gint32 res;
834
835         if (address < 0)
836                 return -1;
837
838         mono_loader_lock ();
839         minfo = _mono_debug_lookup_method (method);
840         if (!minfo || !minfo->il_offsets || !minfo->handle || !minfo->handle->symfile ||
841             !minfo->handle->symfile->offset_table) {
842                 mono_loader_unlock ();
843                 return -1;
844         }
845
846         res = il_offset_from_address (minfo, domain, address);
847         mono_loader_unlock ();
848         return res;
849 }
850
851 /**
852  * mono_debug_address_from_il_offset:
853  * @method:
854  * @il_offset:
855  * @domain:
856  *
857  * Returns: the machine address corresponding to IL offset @il_offset.
858  * The returned value is an offset relative to the beginning of the method @method.
859  */
860 gint32
861 mono_debug_address_from_il_offset (MonoMethod *method, gint32 il_offset, MonoDomain *domain)
862 {
863         MonoDebugMethodInfo *minfo;
864         MonoDebugMethodJitInfo *jit;
865         gint32 res;
866
867         if (il_offset < 0)
868                 return -1;
869
870         mono_loader_lock ();
871         minfo = _mono_debug_lookup_method (method);
872         if (!minfo || !minfo->il_offsets || !minfo->handle || !minfo->handle->symfile ||
873             !minfo->handle->symfile->offset_table) {
874                 mono_loader_unlock ();
875                 return -1;
876         }
877
878         jit = find_method (minfo, domain);
879         if (!jit) {
880                 mono_loader_unlock ();
881                 return -1;
882         }
883
884         res = _mono_debug_address_from_il_offset (jit, il_offset);
885         mono_loader_unlock ();
886         return res;
887 }