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