Fix bugs in sizing TableLayoutPanel (Xamarin bug 18638)
[mono.git] / mono / metadata / mono-debug.c
1 /*
2  * mono-debug.c: 
3  *
4  * Author:
5  *      Mono Project (http://www.mono-project.com)
6  *
7  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
10  */
11
12 #include <config.h>
13 #include <mono/metadata/assembly.h>
14 #include <mono/metadata/tabledefs.h>
15 #include <mono/metadata/tokentype.h>
16 #include <mono/metadata/appdomain.h>
17 #include <mono/metadata/class-internals.h>
18 #include <mono/metadata/mono-debug.h>
19 #include <mono/metadata/mono-debug-debugger.h>
20 #include <mono/metadata/mono-endian.h>
21 #include <mono/metadata/gc-internal.h>
22 #include <string.h>
23
24 #define DATA_TABLE_CHUNK_SIZE           (16384-sizeof (MonoDebugDataChunk))
25
26 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
27
28 #if NO_UNALIGNED_ACCESS
29 #define RETURN_UNALIGNED(type, addr) \
30         { \
31                 type val; \
32                 memcpy(&val, p + offset, sizeof(val)); \
33                 return val; \
34         }
35 #define WRITE_UNALIGNED(type, addr, val) \
36         memcpy(addr, &val, sizeof(type))
37 #define READ_UNALIGNED(type, addr, val) \
38         memcpy(&val, addr, sizeof(type))
39 #else
40 #define RETURN_UNALIGNED(type, addr) \
41         return *(type*)(p + offset);
42 #define WRITE_UNALIGNED(type, addr, val) \
43         (*(type *)(addr) = (val))
44 #define READ_UNALIGNED(type, addr, val) \
45         val = (*(type *)(addr))
46 #endif
47
48 typedef enum {
49         MONO_DEBUG_DATA_ITEM_UNKNOWN            = 0,
50         MONO_DEBUG_DATA_ITEM_CLASS,
51         MONO_DEBUG_DATA_ITEM_METHOD,
52         MONO_DEBUG_DATA_ITEM_DELEGATE_TRAMPOLINE
53 } MonoDebugDataItemType;
54
55 typedef struct _MonoDebugDataChunk MonoDebugDataChunk;
56
57 struct _MonoDebugDataChunk {
58         guint32 total_size;
59         guint32 allocated_size;
60         guint32 current_offset;
61         guint32 dummy;
62         MonoDebugDataChunk *next;
63         guint8 data [MONO_ZERO_LEN_ARRAY];
64 };
65
66 struct _MonoDebugDataTable {
67         gint32 domain;
68         gint32 _dummy; /* alignment for next field. */
69         MonoDebugDataChunk *first_chunk;
70         MonoDebugDataChunk *current_chunk;
71         GHashTable *method_hash;
72         GHashTable *method_address_hash;
73 };
74
75 typedef struct {
76         const gchar *method_name;
77         const gchar *obsolete_cil_code;
78         guint32 wrapper_type;
79 } MonoDebugWrapperData;
80
81 typedef struct {
82         guint32 size;
83         guint32 symfile_id;
84         guint32 domain_id;
85         guint32 method_id;
86         MonoDebugWrapperData *wrapper_data;
87         MonoMethod *method;
88         GSList *address_list;
89 } MonoDebugMethodHeader;
90
91 struct _MonoDebugMethodAddress {
92         MonoDebugMethodHeader header;
93         const guint8 *code_start;
94         const guint8 *wrapper_addr;
95         guint32 code_size;
96         guint8 data [MONO_ZERO_LEN_ARRAY];
97 };
98
99 struct _MonoDebugClassEntry {
100         guint32 size;
101         guint8 data [MONO_ZERO_LEN_ARRAY];
102 };
103
104 typedef struct {
105         gpointer code;
106         guint32 size;
107 } MonoDebugDelegateTrampolineEntry;
108
109 static MonoSymbolTable *mono_symbol_table = NULL;
110 static MonoDebugFormat mono_debug_format = MONO_DEBUG_FORMAT_NONE;
111 static gint32 mono_debug_debugger_version = 5;
112
113 static gboolean mono_debug_initialized = FALSE;
114 static GHashTable *mono_debug_handles = NULL;
115
116 static GHashTable *data_table_hash = NULL;
117 static int next_symbol_file_id = 0;
118
119 static MonoDebugHandle     *mono_debug_open_image      (MonoImage *image, const guint8 *raw_contents, int size);
120
121 static MonoDebugHandle     *_mono_debug_get_image      (MonoImage *image);
122 static void                 mono_debug_add_assembly    (MonoAssembly *assembly,
123                                                         gpointer user_data);
124 static void                 mono_debug_add_type        (MonoClass *klass);
125
126 static MonoDebugHandle     *open_symfile_from_bundle   (MonoImage *image);
127
128 void _mono_debug_init_corlib (MonoDomain *domain);
129
130 extern void (*mono_debugger_class_init_func) (MonoClass *klass);
131
132 static MonoDebugDataTable *
133 create_data_table (MonoDomain *domain)
134 {
135         MonoDebugDataTable *table;
136         MonoDebugDataChunk *chunk;
137
138         table = g_new0 (MonoDebugDataTable, 1);
139         table->domain = domain ? mono_domain_get_id (domain) : -1;
140
141         table->method_address_hash = g_hash_table_new (NULL, NULL);
142         table->method_hash = g_hash_table_new (NULL, NULL);
143
144         chunk = g_malloc0 (sizeof (MonoDebugDataChunk) + DATA_TABLE_CHUNK_SIZE);
145         chunk->total_size = DATA_TABLE_CHUNK_SIZE;
146
147         table->first_chunk = table->current_chunk = chunk;
148
149         if (domain) {
150                 mono_debug_list_add (&mono_symbol_table->data_tables, table);
151                 g_hash_table_insert (data_table_hash, domain, table);
152         }
153
154         return table;
155 }
156
157 static void
158 free_header_data (gpointer key, gpointer value, gpointer user_data)
159 {
160         MonoDebugMethodHeader *header = (MonoDebugMethodHeader*)value;
161
162         if (header->wrapper_data) {
163                 g_free ((gpointer)header->wrapper_data->method_name);
164                 g_free (header->wrapper_data);
165         }
166         g_slist_free (header->address_list);
167 }
168
169 static void
170 free_data_table (MonoDebugDataTable *table)
171 {
172         MonoDebugDataChunk *chunk, *next_chunk;
173
174         g_hash_table_foreach (table->method_hash, free_header_data, NULL);
175         g_hash_table_destroy (table->method_hash);
176         g_hash_table_destroy (table->method_address_hash);
177
178         table->method_hash = NULL;
179         table->method_address_hash = NULL;
180
181         chunk = table->first_chunk;
182         while (chunk) {
183                 next_chunk = chunk->next;
184                 g_free (chunk);
185                 chunk = next_chunk;
186         }
187
188         table->first_chunk = table->current_chunk = NULL;
189         mono_debug_list_remove (&mono_symbol_table->data_tables, table);
190         g_free (table);
191 }
192
193 static MonoDebugDataTable *
194 lookup_data_table (MonoDomain *domain)
195 {
196         MonoDebugDataTable *table;
197
198         table = g_hash_table_lookup (data_table_hash, domain);
199         if (!table) {
200                 g_error ("lookup_data_table () failed for %p\n", domain);
201                 g_assert (table);
202         }
203         return table;
204 }
205
206 static void
207 free_debug_handle (MonoDebugHandle *handle)
208 {
209         if (handle->symfile)
210                 mono_debug_close_mono_symbol_file (handle->symfile);
211         /* decrease the refcount added with mono_image_addref () */
212         free_data_table (handle->type_table);
213         mono_image_close (handle->image);
214         g_free (handle->image_file);
215         g_free (handle);
216 }
217
218 /*
219  * Initialize debugging support.
220  *
221  * This method must be called after loading corlib,
222  * but before opening the application's main assembly because we need to set some
223  * callbacks here.
224  */
225 void
226 mono_debug_init (MonoDebugFormat format)
227 {
228         g_assert (!mono_debug_initialized);
229         if (format == MONO_DEBUG_FORMAT_DEBUGGER)
230                 g_error ("The mdb debugger is no longer supported.");
231
232
233         mono_debug_initialized = TRUE;
234         mono_debug_format = format;
235
236         /*
237          * This must be called before mono_debugger_initialize(), because the
238          * latter registers GC roots.
239          */
240         mono_gc_base_init ();
241
242         mono_debugger_initialize ();
243
244         mono_debugger_lock ();
245
246         mono_symbol_table = g_new0 (MonoSymbolTable, 1);
247         mono_symbol_table->magic = MONO_DEBUGGER_MAGIC;
248         mono_symbol_table->version = MONO_DEBUGGER_MAJOR_VERSION;
249         mono_symbol_table->total_size = sizeof (MonoSymbolTable);
250
251         mono_debug_handles = g_hash_table_new_full
252                 (NULL, NULL, NULL, (GDestroyNotify) free_debug_handle);
253
254         data_table_hash = g_hash_table_new_full (
255                 NULL, NULL, NULL, (GDestroyNotify) free_data_table);
256
257         /* FIXME this is a disgusting hack. Kill it */
258         mono_debugger_class_init_func = mono_debug_add_type;
259         mono_install_assembly_load_hook (mono_debug_add_assembly, NULL);
260
261         mono_symbol_table->global_data_table = create_data_table (NULL);
262
263         mono_debugger_unlock ();
264 }
265
266 /*
267  * INTERNAL USE ONLY !
268  * FIXME this can have a decent name and exist in an internal header
269  */
270 void
271 _mono_debug_init_corlib (MonoDomain *domain)
272 {
273         if (!mono_debug_initialized)
274                 return;
275
276         mono_symbol_table->corlib = mono_debug_open_image (mono_defaults.corlib, NULL, 0);
277 }
278
279 void
280 mono_debug_open_image_from_memory (MonoImage *image, const guint8 *raw_contents, int size)
281 {
282         if (!mono_debug_initialized)
283                 return;
284
285         mono_debug_open_image (image, raw_contents, size);
286 }
287
288 void
289 mono_debug_cleanup (void)
290 {
291         if (mono_debug_handles)
292                 g_hash_table_destroy (mono_debug_handles);
293         mono_debug_handles = NULL;
294
295         if (data_table_hash) {
296                 g_hash_table_destroy (data_table_hash);
297                 data_table_hash = NULL;
298         }
299
300         if (mono_symbol_table) {
301                 if (mono_symbol_table->global_data_table)
302                         free_data_table (mono_symbol_table->global_data_table);
303
304                 g_free (mono_symbol_table);
305                 mono_symbol_table = NULL;
306         }
307 }
308
309 void
310 mono_debug_domain_create (MonoDomain *domain)
311 {
312         MonoDebugDataTable *table;
313
314         if (!mono_debug_initialized)
315                 return;
316
317         mono_debugger_lock ();
318
319         table = create_data_table (domain);
320
321         mono_debugger_unlock ();
322 }
323
324 void
325 mono_debug_domain_unload (MonoDomain *domain)
326 {
327         MonoDebugDataTable *table;
328
329         if (!mono_debug_initialized)
330                 return;
331
332         mono_debugger_lock ();
333
334         table = g_hash_table_lookup (data_table_hash, domain);
335         if (!table) {
336                 g_warning (G_STRLOC ": unloading unknown domain %p / %d",
337                            domain, mono_domain_get_id (domain));
338                 mono_debugger_unlock ();
339                 return;
340         }
341
342         g_hash_table_remove (data_table_hash, domain);
343
344         mono_debugger_unlock ();
345 }
346
347 /*
348  * LOCKING: Assumes the debug lock is held.
349  */
350 static MonoDebugHandle *
351 _mono_debug_get_image (MonoImage *image)
352 {
353         return g_hash_table_lookup (mono_debug_handles, image);
354 }
355
356 void
357 mono_debug_close_image (MonoImage *image)
358 {
359         MonoDebugHandle *handle;
360
361         if (!mono_debug_initialized)
362                 return;
363
364         mono_debugger_lock ();
365
366         handle = _mono_debug_get_image (image);
367         if (!handle) {
368                 mono_debugger_unlock ();
369                 return;
370         }
371
372         mono_debug_list_remove (&mono_symbol_table->symbol_files, handle);
373         g_hash_table_remove (mono_debug_handles, image);
374
375         mono_debugger_unlock ();
376 }
377
378 static MonoDebugHandle *
379 mono_debug_open_image (MonoImage *image, const guint8 *raw_contents, int size)
380 {
381         MonoDebugHandle *handle;
382
383         if (mono_image_is_dynamic (image))
384                 return NULL;
385
386         mono_debugger_lock ();
387
388         handle = _mono_debug_get_image (image);
389         if (handle != NULL) {
390                 mono_debugger_unlock ();
391                 return handle;
392         }
393
394         handle = g_new0 (MonoDebugHandle, 1);
395         handle->index = ++next_symbol_file_id;
396
397         handle->image = image;
398         mono_image_addref (image);
399         handle->image_file = g_strdup (mono_image_get_filename (image));
400
401         handle->type_table = create_data_table (NULL);
402
403         handle->symfile = mono_debug_open_mono_symbols (
404                 handle, raw_contents, size, FALSE);
405
406         mono_debug_list_add (&mono_symbol_table->symbol_files, handle);
407
408         g_hash_table_insert (mono_debug_handles, image, handle);
409
410         mono_debugger_unlock ();
411
412         return handle;
413 }
414
415 static void
416 mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data)
417 {
418         MonoDebugHandle *handle;
419         MonoImage *image;
420
421         mono_debugger_lock ();
422         image = mono_assembly_get_image (assembly);
423         handle = open_symfile_from_bundle (image);
424         if (!handle)
425                 mono_debug_open_image (image, NULL, 0);
426         mono_debugger_unlock ();
427 }
428
429 static guint8 *
430 allocate_data_item (MonoDebugDataTable *table, MonoDebugDataItemType type, guint32 size)
431 {
432         guint32 chunk_size;
433         guint8 *data;
434
435         size = ALIGN_TO (size, sizeof (gpointer));
436
437         if (size + 16 < DATA_TABLE_CHUNK_SIZE)
438                 chunk_size = DATA_TABLE_CHUNK_SIZE;
439         else
440                 chunk_size = size + 16;
441
442         g_assert (table->current_chunk->current_offset == table->current_chunk->allocated_size);
443
444         if (table->current_chunk->allocated_size + size + 8 >= table->current_chunk->total_size) {
445                 MonoDebugDataChunk *new_chunk;
446
447                 new_chunk = g_malloc0 (sizeof (MonoDebugDataChunk) + chunk_size);
448                 new_chunk->total_size = chunk_size;
449
450                 table->current_chunk->next = new_chunk;
451                 table->current_chunk = new_chunk;
452         }
453
454         data = &table->current_chunk->data [table->current_chunk->allocated_size];
455         table->current_chunk->allocated_size += size + 8;
456
457         * ((guint32 *) data) = size;
458         data += 4;
459         * ((guint32 *) data) = type;
460         data += 4;
461         return data;
462 }
463
464 static void
465 write_data_item (MonoDebugDataTable *table, const guint8 *data)
466 {
467         MonoDebugDataChunk *current_chunk = table->current_chunk;
468         guint32 size = * ((guint32 *) (data - 8));
469
470         g_assert (current_chunk->current_offset + size + 8 == current_chunk->allocated_size);
471         current_chunk->current_offset = current_chunk->allocated_size;
472 }
473
474 struct LookupMethodData
475 {
476         MonoDebugMethodInfo *minfo;
477         MonoMethod *method;
478 };
479
480 static void
481 lookup_method_func (gpointer key, gpointer value, gpointer user_data)
482 {
483         MonoDebugHandle *handle = (MonoDebugHandle *) value;
484         struct LookupMethodData *data = (struct LookupMethodData *) user_data;
485
486         if (data->minfo)
487                 return;
488
489         if (handle->symfile)
490                 data->minfo = mono_debug_symfile_lookup_method (handle, data->method);
491 }
492
493 static MonoDebugMethodInfo *
494 _mono_debug_lookup_method (MonoMethod *method)
495 {
496         struct LookupMethodData data;
497
498         data.minfo = NULL;
499         data.method = method;
500
501         if (!mono_debug_handles)
502                 return NULL;
503
504         g_hash_table_foreach (mono_debug_handles, lookup_method_func, &data);
505         return data.minfo;
506 }
507
508 /**
509  * mono_debug_lookup_method:
510  *
511  * Lookup symbol file information for the method @method.  The returned
512  * `MonoDebugMethodInfo' is a private structure, but it can be passed to
513  * mono_debug_symfile_lookup_location().
514  */
515 MonoDebugMethodInfo *
516 mono_debug_lookup_method (MonoMethod *method)
517 {
518         MonoDebugMethodInfo *minfo;
519
520         mono_debugger_lock ();
521         minfo = _mono_debug_lookup_method (method);
522         mono_debugger_unlock ();
523         return minfo;
524 }
525
526 static inline void
527 write_leb128 (guint32 value, guint8 *ptr, guint8 **rptr)
528 {
529         do {
530                 guint8 byte = value & 0x7f;
531                 value >>= 7;
532                 if (value)
533                         byte |= 0x80;
534                 *ptr++ = byte;
535         } while (value);
536
537         *rptr = ptr;
538 }
539
540 static inline void
541 write_sleb128 (gint32 value, guint8 *ptr, guint8 **rptr)
542 {
543         gboolean more = 1;
544
545         while (more) {
546                 guint8 byte = value & 0x7f;
547                 value >>= 7;
548
549                 if (((value == 0) && ((byte & 0x40) == 0)) || ((value == -1) && (byte & 0x40)))
550                         more = 0;
551                 else
552                         byte |= 0x80;
553                 *ptr++ = byte;
554         }
555
556         *rptr = ptr;
557 }
558
559 static void
560 write_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
561 {
562         write_leb128 (var->index, ptr, &ptr);
563         write_sleb128 (var->offset, ptr, &ptr);
564         write_leb128 (var->size, ptr, &ptr);
565         write_leb128 (var->begin_scope, ptr, &ptr);
566         write_leb128 (var->end_scope, ptr, &ptr);
567         WRITE_UNALIGNED (gpointer, ptr, var->type);
568         ptr += sizeof (gpointer);
569         *rptr = ptr;
570 }
571
572 MonoDebugMethodAddress *
573 mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDomain *domain)
574 {
575         MonoMethod *declaring;
576         MonoDebugDataTable *table;
577         MonoDebugMethodHeader *header;
578         MonoDebugMethodAddress *address;
579         MonoDebugMethodInfo *minfo;
580         MonoDebugHandle *handle;
581         guint8 buffer [BUFSIZ];
582         guint8 *ptr, *oldptr;
583         guint32 i, size, total_size, max_size;
584         gboolean is_wrapper = FALSE;
585
586         mono_debugger_lock ();
587
588         table = lookup_data_table (domain);
589
590         handle = _mono_debug_get_image (method->klass->image);
591         minfo = _mono_debug_lookup_method (method);
592
593         if (!minfo || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
594             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
595             (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
596             (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
597             (method->wrapper_type != MONO_WRAPPER_NONE)) {
598                 is_wrapper = TRUE;
599         }
600
601         max_size = (5 * 5) + 1 + (10 * jit->num_line_numbers) +
602                 (25 + sizeof (gpointer)) * (1 + jit->num_params + jit->num_locals);
603
604         if (max_size > BUFSIZ)
605                 ptr = oldptr = g_malloc (max_size);
606         else
607                 ptr = oldptr = buffer;
608
609         write_leb128 (jit->prologue_end, ptr, &ptr);
610         write_leb128 (jit->epilogue_begin, ptr, &ptr);
611
612         write_leb128 (jit->num_line_numbers, ptr, &ptr);
613         for (i = 0; i < jit->num_line_numbers; i++) {
614                 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
615
616                 write_sleb128 (lne->il_offset, ptr, &ptr);
617                 write_sleb128 (lne->native_offset, ptr, &ptr);
618         }
619
620         *ptr++ = jit->this_var ? 1 : 0;
621         if (jit->this_var)
622                 write_variable (jit->this_var, ptr, &ptr);
623
624         write_leb128 (jit->num_params, ptr, &ptr);
625         for (i = 0; i < jit->num_params; i++)
626                 write_variable (&jit->params [i], ptr, &ptr);
627
628         write_leb128 (jit->num_locals, ptr, &ptr);
629         for (i = 0; i < jit->num_locals; i++)
630                 write_variable (&jit->locals [i], ptr, &ptr);
631
632         *ptr++ = jit->gsharedvt_info_var ? 1 : 0;
633         if (jit->gsharedvt_info_var) {
634                 write_variable (jit->gsharedvt_info_var, ptr, &ptr);
635                 write_variable (jit->gsharedvt_locals_var, ptr, &ptr);
636         }
637
638         size = ptr - oldptr;
639         g_assert (size < max_size);
640         total_size = size + sizeof (MonoDebugMethodAddress);
641
642         if (method_is_dynamic (method)) {
643                 address = g_malloc0 (total_size);
644         } else {
645                 address = (MonoDebugMethodAddress *) allocate_data_item (
646                                   table, MONO_DEBUG_DATA_ITEM_METHOD, total_size);
647         }
648
649         address->header.size = total_size;
650         address->header.symfile_id = handle ? handle->index : 0;
651         address->header.domain_id = mono_domain_get_id (domain);
652         address->header.method_id = is_wrapper ? 0 : minfo->index;
653         address->header.method = method;
654
655         address->code_start = jit->code_start;
656         address->code_size = jit->code_size;
657
658         memcpy (&address->data, oldptr, size);
659         if (max_size > BUFSIZ)
660                 g_free (oldptr);
661
662         declaring = method->is_inflated ? ((MonoMethodInflated *) method)->declaring : method;
663         header = g_hash_table_lookup (table->method_hash, declaring);
664
665         if (!header) {
666                 header = &address->header;
667                 g_hash_table_insert (table->method_hash, declaring, header);
668
669                 if (is_wrapper) {
670                         MonoDebugWrapperData *wrapper;
671
672                         header->wrapper_data = wrapper = g_new0 (MonoDebugWrapperData, 1);
673
674                         wrapper->wrapper_type = method->wrapper_type;
675                         wrapper->method_name = mono_method_full_name (declaring, TRUE);
676                         wrapper->obsolete_cil_code = "";
677                 }
678         } else {
679                 address->header.wrapper_data = header->wrapper_data;
680                 header->address_list = g_slist_prepend (header->address_list, address);
681         }
682
683         g_hash_table_insert (table->method_address_hash, method, address);
684
685         if (!method_is_dynamic (method))
686                 write_data_item (table, (guint8 *) address);
687
688         mono_debugger_unlock ();
689         return address;
690 }
691
692 void
693 mono_debug_remove_method (MonoMethod *method, MonoDomain *domain)
694 {
695         MonoMethod *declaring;
696         MonoDebugDataTable *table;
697         MonoDebugMethodHeader *header;
698         MonoDebugMethodAddress *address;
699
700         if (!mono_debug_initialized)
701                 return;
702
703         g_assert (method_is_dynamic (method));
704
705         mono_debugger_lock ();
706
707         table = lookup_data_table (domain);
708
709         declaring = method->is_inflated ? ((MonoMethodInflated *) method)->declaring : method;
710         g_hash_table_remove (table->method_hash, declaring);
711
712         address = g_hash_table_lookup (table->method_address_hash, method);
713         if (address) {
714                 header = &address->header;
715
716                 if (header->wrapper_data) {
717                         g_free ((char*)header->wrapper_data->method_name);
718                         g_free (header->wrapper_data);
719                 }
720                 g_free (address);
721         }
722
723         g_hash_table_remove (table->method_address_hash, method);
724
725         mono_debugger_unlock ();
726 }
727
728 void
729 mono_debug_add_delegate_trampoline (gpointer code, int size)
730 {
731         MonoDebugDelegateTrampolineEntry *entry;
732
733         if (!mono_debug_initialized)
734                 return;
735
736         mono_debugger_lock ();
737
738         entry = (MonoDebugDelegateTrampolineEntry *) allocate_data_item (
739                 mono_symbol_table->global_data_table, MONO_DEBUG_DATA_ITEM_DELEGATE_TRAMPOLINE,
740                 sizeof (MonoDebugDelegateTrampolineEntry));
741         entry->code = code;
742         entry->size = size;
743
744         write_data_item (mono_symbol_table->global_data_table, (guint8 *) entry);
745
746         mono_debugger_unlock ();
747 }
748
749 static inline guint32
750 read_leb128 (guint8 *ptr, guint8 **rptr)
751 {
752         guint32 result = 0, shift = 0;
753
754         while (TRUE) {
755                 guint8 byte = *ptr++;
756
757                 result |= (byte & 0x7f) << shift;
758                 if ((byte & 0x80) == 0)
759                         break;
760                 shift += 7;
761         }
762
763         *rptr = ptr;
764         return result;
765 }
766
767 static inline gint32
768 read_sleb128 (guint8 *ptr, guint8 **rptr)
769 {
770         gint32 result = 0;
771         guint32 shift = 0;
772
773         while (TRUE) {
774                 guint8 byte = *ptr++;
775
776                 result |= (byte & 0x7f) << shift;
777                 shift += 7;
778
779                 if (byte & 0x80)
780                         continue;
781
782                 if ((shift < 32) && (byte & 0x40))
783                         result |= - (1 << shift);
784                 break;
785         }
786
787         *rptr = ptr;
788         return result;
789 }
790
791 static void
792 read_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
793 {
794         var->index = read_leb128 (ptr, &ptr);
795         var->offset = read_sleb128 (ptr, &ptr);
796         var->size = read_leb128 (ptr, &ptr);
797         var->begin_scope = read_leb128 (ptr, &ptr);
798         var->end_scope = read_leb128 (ptr, &ptr);
799         READ_UNALIGNED (gpointer, ptr, var->type);
800         ptr += sizeof (gpointer);
801         *rptr = ptr;
802 }
803
804 void
805 mono_debug_free_method_jit_info (MonoDebugMethodJitInfo *jit)
806 {
807         if (!jit)
808                 return;
809         g_free (jit->line_numbers);
810         g_free (jit->this_var);
811         g_free (jit->params);
812         g_free (jit->locals);
813         g_free (jit->gsharedvt_info_var);
814         g_free (jit->gsharedvt_locals_var);
815         g_free (jit);
816 }
817
818 static MonoDebugMethodJitInfo *
819 mono_debug_read_method (MonoDebugMethodAddress *address)
820 {
821         MonoDebugMethodJitInfo *jit;
822         guint32 i;
823         guint8 *ptr;
824
825         jit = g_new0 (MonoDebugMethodJitInfo, 1);
826         jit->code_start = address->code_start;
827         jit->code_size = address->code_size;
828         jit->wrapper_addr = address->wrapper_addr;
829
830         ptr = (guint8 *) &address->data;
831
832         jit->prologue_end = read_leb128 (ptr, &ptr);
833         jit->epilogue_begin = read_leb128 (ptr, &ptr);
834
835         jit->num_line_numbers = read_leb128 (ptr, &ptr);
836         jit->line_numbers = g_new0 (MonoDebugLineNumberEntry, jit->num_line_numbers);
837         for (i = 0; i < jit->num_line_numbers; i++) {
838                 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
839
840                 lne->il_offset = read_sleb128 (ptr, &ptr);
841                 lne->native_offset = read_sleb128 (ptr, &ptr);
842         }
843
844         if (*ptr++) {
845                 jit->this_var = g_new0 (MonoDebugVarInfo, 1);
846                 read_variable (jit->this_var, ptr, &ptr);
847         }
848
849         jit->num_params = read_leb128 (ptr, &ptr);
850         jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
851         for (i = 0; i < jit->num_params; i++)
852                 read_variable (&jit->params [i], ptr, &ptr);
853
854         jit->num_locals = read_leb128 (ptr, &ptr);
855         jit->locals = g_new0 (MonoDebugVarInfo, jit->num_locals);
856         for (i = 0; i < jit->num_locals; i++)
857                 read_variable (&jit->locals [i], ptr, &ptr);
858
859         if (*ptr++) {
860                 jit->gsharedvt_info_var = g_new0 (MonoDebugVarInfo, 1);
861                 jit->gsharedvt_locals_var = g_new0 (MonoDebugVarInfo, 1);
862                 read_variable (jit->gsharedvt_info_var, ptr, &ptr);
863                 read_variable (jit->gsharedvt_locals_var, ptr, &ptr);
864         }
865
866         return jit;
867 }
868
869 static void
870 mono_debug_add_type (MonoClass *klass)
871 {
872         MonoDebugHandle *handle;
873         MonoDebugClassEntry *entry;
874         guint8 buffer [BUFSIZ];
875         guint8 *ptr, *oldptr;
876         guint32 size, total_size, max_size;
877         int base_offset = 0;
878
879         if (klass->generic_class || klass->rank ||
880             (klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR))
881                 return;
882
883         mono_debugger_lock ();
884
885         handle = _mono_debug_get_image (klass->image);
886         if (!handle) {
887                 mono_debugger_unlock ();
888                 return;
889         }
890
891         max_size = 12 + sizeof (gpointer);
892         if (max_size > BUFSIZ)
893                 ptr = oldptr = g_malloc (max_size);
894         else
895                 ptr = oldptr = buffer;
896
897         if (klass->valuetype)
898                 base_offset = - (int)(sizeof (MonoObject));
899
900         write_leb128 (klass->type_token, ptr, &ptr);
901         write_leb128 (klass->instance_size + base_offset, ptr, &ptr);
902         WRITE_UNALIGNED (gpointer, ptr, klass);
903         ptr += sizeof (gpointer);
904
905         size = ptr - oldptr;
906         g_assert (size < max_size);
907         total_size = size + sizeof (MonoDebugClassEntry);
908
909         g_assert (total_size + 9 < DATA_TABLE_CHUNK_SIZE);
910
911         entry = (MonoDebugClassEntry *) allocate_data_item (
912                 handle->type_table, MONO_DEBUG_DATA_ITEM_CLASS, total_size);
913
914         entry->size = total_size;
915
916         memcpy (&entry->data, oldptr, size);
917
918         write_data_item (handle->type_table, (guint8 *) entry);
919
920         if (max_size > BUFSIZ)
921                 g_free (oldptr);
922
923         mono_debugger_unlock ();
924 }
925
926 static MonoDebugMethodJitInfo *
927 find_method (MonoMethod *method, MonoDomain *domain)
928 {
929         MonoDebugDataTable *table;
930         MonoDebugMethodAddress *address;
931
932         table = lookup_data_table (domain);
933         address = g_hash_table_lookup (table->method_address_hash, method);
934
935         if (!address)
936                 return NULL;
937
938         return mono_debug_read_method (address);
939 }
940
941 MonoDebugMethodJitInfo *
942 mono_debug_find_method (MonoMethod *method, MonoDomain *domain)
943 {
944         MonoDebugMethodJitInfo *res;
945
946         if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
947                 return NULL;
948
949         mono_debugger_lock ();
950         res = find_method (method, domain);
951         mono_debugger_unlock ();
952         return res;
953 }
954
955 struct LookupMethodAddressData
956 {
957         MonoMethod *method;
958         MonoDebugMethodHeader *result;
959 };
960
961 static void
962 lookup_method_address_func (gpointer key, gpointer value, gpointer user_data)
963 {
964         MonoDebugDataTable *table = (MonoDebugDataTable *) value;
965         struct LookupMethodAddressData *data = (struct LookupMethodAddressData *) user_data;
966         MonoDebugMethodHeader *header;
967
968         header = g_hash_table_lookup (table->method_hash, data->method);
969         if (header)
970                 data->result = header;
971 }
972
973 MonoDebugMethodAddressList *
974 mono_debug_lookup_method_addresses (MonoMethod *method)
975 {
976         MonoDebugMethodAddressList *info;
977         MonoDebugMethodHeader *header = NULL;
978         struct LookupMethodAddressData data;
979         MonoMethod *declaring;
980         int count, size;
981         GSList *list;
982         guint8 *ptr;
983
984         g_assert ((mono_debug_debugger_version == 4) || (mono_debug_debugger_version == 5));
985
986         mono_debugger_lock ();
987
988         declaring = method->is_inflated ? ((MonoMethodInflated *) method)->declaring : method;
989
990         data.method = declaring;
991         data.result = NULL;
992
993         g_hash_table_foreach (data_table_hash, lookup_method_address_func, &data);
994         header = data.result;
995
996         if (!header) {
997                 mono_debugger_unlock ();
998                 return NULL;
999         }
1000
1001         count = g_slist_length (header->address_list) + 1;
1002         size = sizeof (MonoDebugMethodAddressList) + count * sizeof (gpointer);
1003
1004         info = g_malloc0 (size);
1005         info->size = size;
1006         info->count = count;
1007
1008         ptr = info->data;
1009
1010         WRITE_UNALIGNED (gpointer, ptr, header);
1011         ptr += sizeof (gpointer);
1012
1013         for (list = header->address_list; list; list = list->next) {
1014                 WRITE_UNALIGNED (gpointer, ptr, list->data);
1015                 ptr += sizeof (gpointer);
1016         }
1017
1018         mono_debugger_unlock ();
1019         return info;
1020 }
1021
1022 static gint32
1023 il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint32 native_offset)
1024 {
1025         MonoDebugMethodJitInfo *jit;
1026         int i;
1027
1028         jit = find_method (method, domain);
1029         if (!jit || !jit->line_numbers)
1030                 goto cleanup_and_fail;
1031
1032         for (i = jit->num_line_numbers - 1; i >= 0; i--) {
1033                 MonoDebugLineNumberEntry lne = jit->line_numbers [i];
1034
1035                 if (lne.native_offset <= native_offset) {
1036                         mono_debug_free_method_jit_info (jit);
1037                         return lne.il_offset;
1038                 }
1039         }
1040
1041 cleanup_and_fail:
1042         mono_debug_free_method_jit_info (jit);
1043         return -1;
1044 }
1045
1046 /**
1047  * mono_debug_il_offset_from_address:
1048  *
1049  *   Compute the IL offset corresponding to NATIVE_OFFSET inside the native
1050  * code of METHOD in DOMAIN.
1051  */
1052 gint32
1053 mono_debug_il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint32 native_offset)
1054 {
1055         gint32 res;
1056
1057         mono_debugger_lock ();
1058
1059         res = il_offset_from_address (method, domain, native_offset);
1060
1061         mono_debugger_unlock ();
1062
1063         return res;
1064 }
1065
1066 /**
1067  * mono_debug_lookup_source_location:
1068  * @address: Native offset within the @method's machine code.
1069  *
1070  * Lookup the source code corresponding to the machine instruction located at
1071  * native offset @address within @method.
1072  *
1073  * The returned `MonoDebugSourceLocation' contains both file / line number
1074  * information and the corresponding IL offset.  It must be freed by
1075  * mono_debug_free_source_location().
1076  */
1077 MonoDebugSourceLocation *
1078 mono_debug_lookup_source_location (MonoMethod *method, guint32 address, MonoDomain *domain)
1079 {
1080         MonoDebugMethodInfo *minfo;
1081         MonoDebugSourceLocation *location;
1082         gint32 offset;
1083
1084         if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
1085                 return NULL;
1086
1087         mono_debugger_lock ();
1088         minfo = _mono_debug_lookup_method (method);
1089         if (!minfo || !minfo->handle || !minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile)) {
1090                 mono_debugger_unlock ();
1091                 return NULL;
1092         }
1093
1094         offset = il_offset_from_address (method, domain, address);
1095         if (offset < 0) {
1096                 mono_debugger_unlock ();
1097                 return NULL;
1098         }
1099
1100         location = mono_debug_symfile_lookup_location (minfo, offset);
1101         mono_debugger_unlock ();
1102         return location;
1103 }
1104
1105 /*
1106  * mono_debug_lookup_locals:
1107  *
1108  *   Return information about the local variables of MINFO.
1109  * The result should be freed using mono_debug_symfile_free_locals ().
1110  */
1111 MonoDebugLocalsInfo*
1112 mono_debug_lookup_locals (MonoMethod *method)
1113 {
1114         MonoDebugMethodInfo *minfo;
1115         MonoDebugLocalsInfo *res;
1116
1117         if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
1118                 return NULL;
1119
1120         mono_debugger_lock ();
1121         minfo = _mono_debug_lookup_method (method);
1122         if (!minfo || !minfo->handle || !minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile)) {
1123                 mono_debugger_unlock ();
1124                 return NULL;
1125         }
1126
1127         res = mono_debug_symfile_lookup_locals (minfo);
1128         mono_debugger_unlock ();
1129
1130         return res;
1131 }
1132
1133 /**
1134  * mono_debug_free_source_location:
1135  * @location: A `MonoDebugSourceLocation'.
1136  *
1137  * Frees the @location.
1138  */
1139 void
1140 mono_debug_free_source_location (MonoDebugSourceLocation *location)
1141 {
1142         if (location) {
1143                 g_free (location->source_file);
1144                 g_free (location);
1145         }
1146 }
1147
1148 /**
1149  * mono_debug_print_stack_frame:
1150  * @native_offset: Native offset within the @method's machine code.
1151  *
1152  * Conventient wrapper around mono_debug_lookup_source_location() which can be
1153  * used if you only want to use the location to print a stack frame.
1154  */
1155 gchar *
1156 mono_debug_print_stack_frame (MonoMethod *method, guint32 native_offset, MonoDomain *domain)
1157 {
1158         MonoDebugSourceLocation *location;
1159         gchar *fname, *ptr, *res;
1160         int offset;
1161
1162         fname = mono_method_full_name (method, TRUE);
1163         for (ptr = fname; *ptr; ptr++) {
1164                 if (*ptr == ':') *ptr = '.';
1165         }
1166
1167         location = mono_debug_lookup_source_location (method, native_offset, domain);
1168
1169         if (!location) {
1170                 if (mono_debug_initialized) {
1171                         mono_debugger_lock ();
1172                         offset = il_offset_from_address (method, domain, native_offset);
1173                         mono_debugger_unlock ();
1174                 } else {
1175                         offset = -1;
1176                 }
1177
1178                 if (offset < 0)
1179                         res = g_strdup_printf ("at %s <0x%05x>", fname, native_offset);
1180                 else
1181                         res = g_strdup_printf ("at %s <IL 0x%05x, 0x%05x>", fname, offset, native_offset);
1182                 g_free (fname);
1183                 return res;
1184         }
1185
1186         res = g_strdup_printf ("at %s [0x%05x] in %s:%d", fname, location->il_offset,
1187                                location->source_file, location->row);
1188
1189         g_free (fname);
1190         mono_debug_free_source_location (location);
1191         return res;
1192 }
1193
1194 void
1195 mono_debug_list_add (MonoDebugList **list, gconstpointer data)
1196 {
1197         MonoDebugList *element, **ptr;
1198
1199         element = g_new0 (MonoDebugList, 1);
1200         element->data = data;
1201
1202         for (ptr = list; *ptr; ptr = &(*ptr)->next)
1203                 ;
1204
1205         *ptr = element;
1206 }
1207
1208 void
1209 mono_debug_list_remove (MonoDebugList **list, gconstpointer data)
1210 {
1211         MonoDebugList **ptr;
1212         MonoDebugList *next;
1213
1214         for (ptr = list; *ptr; ptr = &(*ptr)->next) {
1215                 if ((*ptr)->data != data)
1216                         continue;
1217
1218                 next = (*ptr)->next;
1219                 g_free ((*ptr));
1220                 *ptr = next;
1221                 break;
1222         }
1223 }
1224
1225 static gboolean is_attached = FALSE;
1226
1227 void
1228 mono_set_is_debugger_attached (gboolean attached)
1229 {
1230         is_attached = attached;
1231 }
1232
1233 gboolean
1234 mono_is_debugger_attached (void)
1235 {
1236         return is_attached;
1237 }
1238
1239 /*
1240  * Bundles
1241  */
1242
1243 typedef struct _BundledSymfile BundledSymfile;
1244
1245 struct _BundledSymfile {
1246         BundledSymfile *next;
1247         const char *aname;
1248         const mono_byte *raw_contents;
1249         int size;
1250 };
1251
1252 static BundledSymfile *bundled_symfiles = NULL;
1253
1254 void
1255 mono_register_symfile_for_assembly (const char *assembly_name, const mono_byte *raw_contents, int size)
1256 {
1257         BundledSymfile *bsymfile;
1258
1259         bsymfile = g_new0 (BundledSymfile, 1);
1260         bsymfile->aname = assembly_name;
1261         bsymfile->raw_contents = raw_contents;
1262         bsymfile->size = size;
1263         bsymfile->next = bundled_symfiles;
1264         bundled_symfiles = bsymfile;
1265 }
1266
1267 static MonoDebugHandle *
1268 open_symfile_from_bundle (MonoImage *image)
1269 {
1270         BundledSymfile *bsymfile;
1271
1272         for (bsymfile = bundled_symfiles; bsymfile; bsymfile = bsymfile->next) {
1273                 if (strcmp (bsymfile->aname, image->module_name))
1274                         continue;
1275
1276                 return mono_debug_open_image (image, bsymfile->raw_contents, bsymfile->size);
1277         }
1278
1279         return NULL;
1280 }
1281
1282 /**
1283  * mono_debug_enabled:
1284  *
1285  * Returns true is debug information is enabled. This doesn't relate if a debugger is present or not.
1286  */
1287 mono_bool
1288 mono_debug_enabled (void)
1289 {
1290         return mono_debug_format != MONO_DEBUG_FORMAT_NONE;
1291 }