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