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