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