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