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