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