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