5 #include <mono/metadata/class.h>
6 #include <mono/metadata/tabledefs.h>
7 #include <mono/metadata/tokentype.h>
8 #include <mono/metadata/debug-mono-symfile.h>
9 #include <mono/jit/codegen.h>
10 #include <mono/jit/debug.h>
12 #include "debug-private.h"
14 /* See debug.h for documentation. */
15 guint32 mono_debugger_symbol_file_table_generation = 0;
16 guint8 *mono_debugger_symbol_file_table = NULL;
18 /* Caution: This function MUST be called before touching the symbol table! */
19 static void release_symbol_file_table (void);
21 static MonoDebugHandle *mono_debug_handles = NULL;
22 static MonoDebugHandle *mono_default_debug_handle = NULL;
25 * This is a global data symbol which is read by the debugger.
27 MonoDebuggerInfo MONO_DEBUGGER__debugger_info = {
28 MONO_SYMBOL_FILE_MAGIC,
29 MONO_SYMBOL_FILE_VERSION,
30 sizeof (MonoDebuggerInfo),
31 &mono_generic_trampoline_code,
32 &mono_debugger_symbol_file_table_generation,
33 &mono_debugger_symbol_file_table,
34 &mono_debugger_update_symbol_file_table,
39 free_method_info (MonoDebugMethodInfo *minfo)
41 DebugMethodInfo *priv = minfo->user_data;
44 if (priv->line_numbers)
45 g_ptr_array_free (priv->line_numbers, TRUE);
52 g_free (minfo->jit->il_addresses);
53 g_free (minfo->jit->this_var);
54 g_free (minfo->jit->params);
55 g_free (minfo->jit->locals);
59 g_free (minfo->il_offsets);
64 debug_arg_warning (const char *message)
66 g_warning ("Error while processing --debug-args arguments: %s", message);
70 replace_suffix (const char *filename, const char *new_suffix)
72 const char *pos = strrchr (filename, '.');
75 return g_strdup_printf ("%s.%s", filename, new_suffix);
77 int len = pos - filename;
78 gchar *retval = g_malloc0 (len + strlen (new_suffix) + 2);
79 memcpy (retval, filename, len);
81 memcpy (retval + len + 1, new_suffix, strlen (new_suffix) + 1);
87 mono_debug_open (const char *name, MonoDebugFormat format, const char **args)
89 MonoDebugHandle *debug;
92 release_symbol_file_table ();
94 debug = g_new0 (MonoDebugHandle, 1);
95 debug->name = g_strdup (name);
96 debug->format = format;
97 debug->producer_name = g_strdup_printf ("Mono JIT compiler version %s", VERSION);
98 debug->next_idx = 100;
101 debug->type_hash = g_hash_table_new (NULL, NULL);
102 debug->source_files = g_ptr_array_new ();
104 for (ptr = args; ptr && *ptr; ptr++) {
105 const char *arg = *ptr;
108 switch (debug->format) {
109 case MONO_DEBUG_FORMAT_STABS:
110 case MONO_DEBUG_FORMAT_DWARF2:
111 if (!strncmp (arg, "filename=", 9)) {
113 debug_arg_warning ("The `filename' argument can be given only once.");
114 debug->filename = g_strdup (arg + 9);
116 } else if (!strncmp (arg, "objfile=", 8)) {
118 debug_arg_warning ("The `objfile' argument can be given only once.");
119 debug->objfile = g_strdup (arg + 8);
123 case MONO_DEBUG_FORMAT_MONO:
124 debug->flags |= MONO_DEBUG_FLAGS_DONT_UPDATE_IL_FILES |
125 MONO_DEBUG_FLAGS_DONT_CREATE_IL_FILES;
131 if (debug->format != MONO_DEBUG_FORMAT_MONO) {
132 if (!strcmp (arg, "dont_assemble")) {
133 debug->flags |= MONO_DEBUG_FLAGS_DONT_ASSEMBLE;
135 } else if (!strcmp (arg, "update_on_exit")) {
136 debug->flags |= MONO_DEBUG_FLAGS_UPDATE_ON_EXIT;
138 } else if (!strcmp (arg, "install_il_files")) {
139 debug->flags |= MONO_DEBUG_FLAGS_INSTALL_IL_FILES;
141 } else if (!strcmp (arg, "dont_update_il_files")) {
142 debug->flags |= MONO_DEBUG_FLAGS_DONT_UPDATE_IL_FILES;
144 } else if (!strcmp (arg, "dont_create_il_files")) {
145 debug->flags |= MONO_DEBUG_FLAGS_DONT_CREATE_IL_FILES;
149 if (!strcmp (arg, "internal_mono_debugger")) {
150 debug->flags |= MONO_DEBUG_FLAGS_MONO_DEBUGGER;
155 message = g_strdup_printf ("Unknown argument `%s'.", arg);
156 debug_arg_warning (message);
160 switch (debug->format) {
161 case MONO_DEBUG_FORMAT_STABS:
162 if (!debug->filename)
163 debug->filename = g_strdup_printf ("%s-stabs.s", g_basename (debug->name));
165 debug->objfile = g_strdup_printf ("%s.o", g_basename (debug->name));
167 case MONO_DEBUG_FORMAT_DWARF2:
168 if (!debug->filename)
169 debug->filename = g_strdup_printf ("%s-dwarf.s", g_basename (debug->name));
171 debug->objfile = g_strdup_printf ("%s.o", g_basename (debug->name));
173 case MONO_DEBUG_FORMAT_MONO:
176 g_assert_not_reached ();
179 debug->next = mono_debug_handles;
180 mono_debug_handles = debug;
182 if (!mono_default_debug_handle)
183 mono_default_debug_handle = debug;
189 generate_il_offsets (AssemblyDebugInfo *info, MonoMethod *method)
191 GPtrArray *il_offsets = g_ptr_array_new ();
192 MonoClass *klass = method->klass;
193 MonoDebugMethodInfo *minfo;
194 DebugMethodInfo *priv;
197 g_assert (klass->image == info->image);
199 /* FIXME: doesn't work yet. */
200 if (!strcmp (klass->name_space, "System.Runtime.Remoting.Proxies"))
203 mono_class_init (klass);
205 minfo = g_new0 (MonoDebugMethodInfo, 1);
206 minfo->method = method;
207 minfo->user_data = priv = g_new0 (DebugMethodInfo, 1);
209 priv->name = g_strdup_printf ("%s%s%s.%s", klass->name_space, klass->name_space [0]? ".": "",
210 klass->name, method->name);
211 priv->source_file = info->source_file;
215 * Find the method index in the image.
217 for (i = 0; klass->methods && i < klass->method.count; ++i) {
218 if (klass->methods [i] == minfo->method) {
219 priv->method_number = klass->method.first + i + 1;
220 priv->first_line = info->mlines [priv->method_number];
225 g_assert (priv->method_number);
227 /* info->moffsets contains -1 "outside" of functions. */
228 for (i = priv->first_line; (i > 0) && (info->moffsets [i] == 0); i--)
230 priv->start_line = i + 1;
232 for (i = priv->start_line; info->moffsets [i] != -1; i++) {
233 MonoSymbolFileLineNumberEntry *lne = g_new0 (MonoSymbolFileLineNumberEntry, 1);
235 if (!info->moffsets [i] && (i > priv->start_line))
238 lne->offset = info->moffsets [i];
241 g_ptr_array_add (il_offsets, lne);
246 minfo->num_il_offsets = il_offsets->len;
247 minfo->il_offsets = g_new0 (MonoSymbolFileLineNumberEntry, il_offsets->len);
248 for (i = 0; i < il_offsets->len; i++) {
249 MonoSymbolFileLineNumberEntry *il = g_ptr_array_index (il_offsets, i);
251 minfo->il_offsets [i] = *il;
254 g_ptr_array_free (il_offsets, TRUE);
256 g_hash_table_insert (info->methods, method, minfo);
260 debug_load_method_lines (AssemblyDebugInfo* info)
262 MonoTableInfo *table = &info->image->tables [MONO_TABLE_METHOD];
268 if (info->always_create_il || !(info->handle->flags & MONO_DEBUG_FLAGS_DONT_UPDATE_IL_FILES)) {
269 char *command = g_strdup_printf ("monodis --output=%s %s",
270 info->ilfile, info->image->name);
271 struct stat stata, statb;
272 int need_update = FALSE;
274 if (stat (info->image->name, &stata)) {
275 g_warning ("cannot access assembly file (%s): %s",
276 info->image->name, g_strerror (errno));
281 /* If the stat() failed or the file is older. */
282 if (stat (info->ilfile, &statb)) {
283 /* Don't create any new *.il files if the user told us not to do so. */
284 if (!(info->handle->flags & MONO_DEBUG_FLAGS_DONT_CREATE_IL_FILES))
286 } else if (statb.st_mtime < stata.st_mtime)
290 g_print ("Recreating %s from %s.\n", info->ilfile, info->image->name);
291 if (system (command)) {
292 g_warning ("cannot create IL assembly file (%s): %s",
293 command, g_strerror (errno));
300 /* use an env var with directories for searching. */
301 if (!(f = fopen (info->ilfile, "r"))) {
302 g_warning ("cannot open IL assembly file %s", info->ilfile);
306 info->total_lines = 100;
307 info->moffsets = g_malloc (info->total_lines * sizeof (int));
310 while (fgets (buf, sizeof (buf), f)) {
313 info->moffsets [i++] = offset;
314 if (i + 2 >= info->total_lines) {
315 info->total_lines += 100;
316 info->moffsets = g_realloc (info->moffsets, info->total_lines * sizeof (int));
317 g_assert (info->moffsets);
320 if (!sscanf (buf, " // method line %d", &mnum))
325 if (mnum >= info->nmethods)
328 while (fgets (buf, sizeof (buf), f)) {
332 if (i + 2 >= info->total_lines) {
333 info->total_lines += 100;
334 info->moffsets = g_realloc (info->moffsets, info->total_lines * sizeof (int));
335 g_assert (info->moffsets);
338 if (strstr (buf, "}")) {
343 if (sscanf (buf, " IL_%x:", &newoffset)) {
349 info->moffsets [i] = offset;
351 /* g_print ("method %d found at %d\n", mnum, pos); */
352 info->mlines [mnum] = pos;
356 for (idx = 1; idx <= table->rows; idx++) {
357 guint32 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
358 MonoMethod *method = mono_get_method (info->image, token, NULL);
360 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
361 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
362 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
365 if (method->wrapper_type != MONO_WRAPPER_NONE)
368 generate_il_offsets (info, method);
373 record_line_number (DebugMethodInfo *priv, gconstpointer address, guint32 line, int is_basic_block)
375 DebugLineNumberInfo *lni = g_new0 (DebugLineNumberInfo, 1);
377 lni->address = address;
379 lni->is_basic_block = is_basic_block;
380 lni->source_file = priv->source_file;
382 g_ptr_array_add (priv->line_numbers, lni);
386 debug_generate_method_lines (AssemblyDebugInfo *info, MonoDebugMethodInfo *minfo, MonoFlowGraph* cfg)
388 guint32 st_address, st_line;
389 DebugMethodInfo *priv = minfo->user_data;
395 priv->line_numbers = g_ptr_array_new ();
397 st_line = priv->first_line;
398 st_address = minfo->jit->prologue_end;
400 /* record_line_number takes absolute memory addresses. */
401 record_line_number (priv, minfo->jit->code_start, priv->start_line, FALSE);
403 /* This is the first actual code line of the method. */
404 record_line_number (priv, minfo->jit->code_start + st_address, st_line, TRUE);
406 /* start lines of basic blocks */
407 for (i = 0; i < cfg->block_count; ++i) {
410 for (j = 0; cfg->bblocks [i].forest && (j < cfg->bblocks [i].forest->len); ++j) {
411 MBTree *t = (MBTree *) g_ptr_array_index (cfg->bblocks [i].forest, j);
412 gint32 line_inc = 0, addr_inc;
415 st_line = priv->first_line;
416 st_address = t->addr;
418 record_line_number (priv, cfg->start + st_address, st_line, TRUE);
421 addr_inc = t->addr - st_address;
422 st_address += addr_inc;
427 if (t->cli_addr != -1) {
428 int *lines = info->moffsets + st_line;
431 while ((*k != -1) && (*k < t->cli_addr))
434 line_inc = k - lines;
439 record_line_number (priv, minfo->jit->code_start + st_address,
446 debug_update_il_offsets (AssemblyDebugInfo *info, MonoDebugMethodInfo *minfo, MonoFlowGraph* cfg)
448 guint32 old_address, st_address;
451 minfo->jit->il_addresses = g_new0 (guint32, minfo->num_il_offsets);
452 if (minfo->num_il_offsets < 2)
455 st_address = old_address = minfo->jit->prologue_end;
457 minfo->jit->il_addresses [0] = 0;
458 minfo->jit->il_addresses [1] = st_address;
461 /* start lines of basic blocks */
462 for (i = 0; i < cfg->block_count; ++i) {
465 for (j = 0; cfg->bblocks [i].forest && (j < cfg->bblocks [i].forest->len); ++j) {
466 MBTree *t = (MBTree *) g_ptr_array_index (cfg->bblocks [i].forest, j);
470 st_address = t->addr;
472 addr_inc = t->addr - st_address;
473 st_address += addr_inc;
475 if (t->cli_addr == -1)
478 while (minfo->il_offsets [index].offset < t->cli_addr) {
479 minfo->jit->il_addresses [index] = old_address;
480 if (++index >= minfo->num_il_offsets)
484 minfo->jit->il_addresses [index] = st_address;
485 old_address = st_address;
489 while (index < minfo->num_il_offsets)
490 minfo->jit->il_addresses [index++] = minfo->jit->epilogue_begin;
493 static AssemblyDebugInfo *
494 mono_debug_get_image (MonoDebugHandle* debug, MonoImage *image)
497 AssemblyDebugInfo *info;
499 if (debug->format == MONO_DEBUG_FORMAT_NONE)
502 for (tmp = debug->info; tmp; tmp = tmp->next) {
503 info = (AssemblyDebugInfo*)tmp->data;
505 if (info->image == image)
512 static AssemblyDebugInfo *
513 mono_debug_open_image (MonoDebugHandle* debug, MonoImage *image)
515 AssemblyDebugInfo *info;
517 info = mono_debug_get_image (debug, image);
522 if (!strcmp (image->assembly_name, "corlib"))
528 info = g_new0 (AssemblyDebugInfo, 1);
530 info->image->ref_count++;
531 info->name = g_strdup (image->assembly_name);
532 info->format = debug->format;
533 info->handle = debug;
534 info->methods = g_hash_table_new_full (g_direct_hash, g_direct_equal,
535 NULL, (GDestroyNotify) free_method_info);
537 info->source_file = debug->source_files->len;
538 g_ptr_array_add (debug->source_files, g_strdup_printf ("%s.il", image->assembly_name));
540 debug->info = g_list_prepend (debug->info, info);
542 info->nmethods = image->tables [MONO_TABLE_METHOD].rows + 1;
543 info->mlines = g_new0 (int, info->nmethods);
545 switch (info->format) {
546 case MONO_DEBUG_FORMAT_STABS:
547 case MONO_DEBUG_FORMAT_DWARF2:
548 if (debug->flags & MONO_DEBUG_FLAGS_INSTALL_IL_FILES) {
549 gchar *dirname = g_path_get_dirname (image->name);
550 info->ilfile = g_strdup_printf ("%s/%s.il", dirname, info->name);
553 info->ilfile = g_strdup_printf ("%s.il", info->name);
555 case MONO_DEBUG_FORMAT_MONO:
556 info->filename = replace_suffix (image->name, "dbg");
557 if (g_file_test (info->filename, G_FILE_TEST_EXISTS))
558 info->symfile = mono_debug_open_mono_symbol_file (info->image, info->filename, TRUE);
559 else if (debug->flags & MONO_DEBUG_FLAGS_MONO_DEBUGGER)
560 info->symfile = mono_debug_create_mono_symbol_file (info->image);
561 mono_debugger_symbol_file_table_generation++;
568 if (debug->format != MONO_DEBUG_FORMAT_MONO)
569 debug_load_method_lines (info);
575 mono_debug_add_image (MonoDebugHandle* debug, MonoImage *image)
577 mono_debug_open_image (debug, image);
581 mono_debug_write_symbols (MonoDebugHandle *debug)
585 if (!debug || !debug->dirty)
588 release_symbol_file_table ();
590 switch (debug->format) {
591 case MONO_DEBUG_FORMAT_STABS:
592 mono_debug_write_stabs (debug);
594 case MONO_DEBUG_FORMAT_DWARF2:
595 mono_debug_write_dwarf2 (debug);
597 case MONO_DEBUG_FORMAT_MONO:
598 for (tmp = debug->info; tmp; tmp = tmp->next) {
599 AssemblyDebugInfo *info = (AssemblyDebugInfo*)tmp->data;
604 mono_debug_update_mono_symbol_file (info->symfile);
608 g_assert_not_reached ();
611 debug->dirty = FALSE;
615 mono_debug_make_symbols (void)
617 MonoDebugHandle *debug;
619 for (debug = mono_debug_handles; debug; debug = debug->next)
620 mono_debug_write_symbols (debug);
624 mono_debug_close_assembly (AssemblyDebugInfo* info)
626 switch (info->format) {
627 case MONO_DEBUG_FORMAT_MONO:
628 if (info->symfile != NULL)
629 mono_debug_close_mono_symbol_file (info->symfile);
634 g_hash_table_destroy (info->methods);
635 g_free (info->mlines);
636 g_free (info->moffsets);
638 g_free (info->ilfile);
639 g_free (info->filename);
640 g_free (info->objfile);
645 mono_debug_cleanup (void)
647 MonoDebugHandle *debug, *temp;
649 release_symbol_file_table ();
651 for (debug = mono_debug_handles; debug; debug = temp) {
654 if (debug->flags & MONO_DEBUG_FLAGS_UPDATE_ON_EXIT)
655 mono_debug_write_symbols (debug);
658 for (tmp = debug->info; tmp; tmp = tmp->next) {
659 AssemblyDebugInfo* info = (AssemblyDebugInfo*)tmp->data;
661 mono_debug_close_assembly (info);
664 g_ptr_array_free (debug->source_files, TRUE);
665 g_hash_table_destroy (debug->type_hash);
666 g_free (debug->producer_name);
667 g_free (debug->name);
673 mono_debug_handles = NULL;
674 mono_default_debug_handle = NULL;
678 mono_debug_get_type (MonoDebugHandle *debug, MonoClass *klass)
682 mono_class_init (klass);
684 index = GPOINTER_TO_INT (g_hash_table_lookup (debug->type_hash, klass));
690 index = ++debug->next_klass_idx;
691 g_hash_table_insert (debug->type_hash, klass, GINT_TO_POINTER (index));
696 switch (klass->byval_arg.type) {
697 case MONO_TYPE_CLASS:
699 mono_debug_get_type (debug, klass->parent);
701 for (i = 0; i < klass->method.count; i++) {
702 MonoMethod *method = klass->methods [i];
703 MonoType *ret_type = NULL;
706 if (method->signature->ret->type != MONO_TYPE_VOID)
707 ret_type = method->signature->ret;
710 MonoClass *ret_klass = mono_class_from_mono_type (ret_type);
711 mono_debug_get_type (debug, ret_klass);
714 for (j = 0; j < method->signature->param_count; j++) {
715 MonoType *sub_type = method->signature->params [j];
716 MonoClass *sub_klass = mono_class_from_mono_type (sub_type);
717 mono_debug_get_type (debug, sub_klass);
721 case MONO_TYPE_VALUETYPE:
722 for (i = 0; i < klass->field.count; i++) {
723 MonoClass *subclass = mono_class_from_mono_type (klass->fields [i].type);
724 mono_debug_get_type (debug, subclass);
727 case MONO_TYPE_ARRAY:
728 case MONO_TYPE_SZARRAY:
729 mono_debug_get_type (debug, klass->element_class);
739 mono_debug_handle_from_class (MonoClass *klass)
741 MonoDebugHandle *debug;
743 mono_class_init (klass);
745 for (debug = mono_debug_handles; debug; debug = debug->next) {
748 for (tmp = debug->info; tmp; tmp = tmp->next) {
749 AssemblyDebugInfo *info = (AssemblyDebugInfo*)tmp->data;
751 if (info->image == klass->image)
760 il_offset_from_address (MonoDebugMethodInfo *minfo, guint32 address)
767 for (i = 0; i < minfo->num_il_offsets; i++)
768 if (minfo->jit->il_addresses [i] > address)
769 return minfo->il_offsets [i].offset;
775 address_from_il_offset (MonoDebugMethodInfo *minfo, guint32 il_offset)
782 for (i = 0; i < minfo->num_il_offsets; i++)
783 if (minfo->il_offsets [i].offset > il_offset)
784 return minfo->jit->il_addresses [i];
790 mono_debug_add_type (MonoClass *klass)
792 MonoDebugHandle *debug = mono_debug_handle_from_class (klass);
794 g_assert (debug != NULL);
796 mono_debug_get_type (debug, klass);
800 il_offset_from_position (MonoFlowGraph *cfg, MonoPosition *pos)
805 if (pos->abs_pos == 0)
808 if (pos->pos.bid >= cfg->block_count)
811 bblock = &cfg->bblocks [pos->pos.bid];
812 if (pos->pos.tid >= bblock->forest->len)
815 tree = (MBTree *) g_ptr_array_index (bblock->forest, pos->pos.tid);
817 return tree->cli_addr;
820 static MonoDebugMethodInfo *
821 lookup_method (MonoMethod *method)
823 MonoDebugHandle *debug;
825 for (debug = mono_debug_handles; debug; debug = debug->next) {
828 for (tmp = debug->info; tmp; tmp = tmp->next) {
829 AssemblyDebugInfo *info = (AssemblyDebugInfo*)tmp->data;
830 MonoDebugMethodInfo *minfo;
833 minfo = mono_debug_find_method (info->symfile, method);
835 minfo = g_hash_table_lookup (info->methods, method);
846 mono_debug_add_method (MonoFlowGraph *cfg)
848 MonoMethod *method = cfg->method;
849 MonoClass *klass = method->klass;
850 MonoDebugHandle* debug;
851 AssemblyDebugInfo* info;
852 MonoDebugMethodJitInfo *jit;
853 MonoDebugMethodInfo *minfo;
856 mono_class_init (klass);
858 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
859 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
860 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
863 if (method->wrapper_type != MONO_WRAPPER_NONE)
866 debug = mono_debug_handle_from_class (klass);
868 if (mono_default_debug_handle)
869 debug = mono_default_debug_handle;
874 release_symbol_file_table ();
876 info = mono_debug_open_image (debug, klass->image);
878 minfo = lookup_method (method);
879 if (!minfo || minfo->jit)
884 mono_debugger_symbol_file_table_generation++;
886 minfo->jit = jit = g_new0 (MonoDebugMethodJitInfo, 1);
887 jit->code_start = cfg->start;
888 jit->code_size = cfg->epilogue_end;
889 jit->prologue_end = cfg->prologue_end;
890 jit->epilogue_begin = cfg->epilog;
891 jit->num_params = method->signature->param_count;
892 jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
894 if (method->signature->hasthis) {
895 MonoVarInfo *ptr = ((MonoVarInfo *) cfg->varinfo->data) + cfg->args_start_index;
897 jit->this_var = g_new0 (MonoDebugVarInfo, 1);
898 jit->this_var->offset = ptr->offset;
901 for (i = 0; i < jit->num_params; i++) {
902 MonoVarInfo *ptr = ((MonoVarInfo *) cfg->varinfo->data) + cfg->args_start_index +
903 method->signature->hasthis;
905 jit->params [i].offset = ptr [i].offset;
908 debug_generate_method_lines (info, minfo, cfg);
909 debug_update_il_offsets (info, minfo, cfg);
911 if (!method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
912 MonoMethodHeader *header = ((MonoMethodNormal*)method)->header;
913 MonoVarInfo *ptr = ((MonoVarInfo *) cfg->varinfo->data) + cfg->locals_start_index;
914 MonoDebugVarInfo *locals;
916 locals = g_new0 (MonoDebugVarInfo, header->num_locals);
917 for (i = 0; i < header->num_locals; i++) {
918 gint32 begin_offset, end_offset;
919 gint32 begin_scope, end_scope;
921 if (ptr [i].reg >= 0) {
922 locals [i].index = ptr [i].reg | MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER;
923 locals [i].offset = 0;
925 locals [i].offset = ptr [i].offset;
927 begin_offset = il_offset_from_position (cfg, &ptr [i].range.first_use);
928 end_offset = il_offset_from_position (cfg, &ptr [i].range.last_use);
932 begin_scope = address_from_il_offset (minfo, begin_offset);
933 end_scope = address_from_il_offset (minfo, end_offset);
936 locals [i].begin_scope = begin_scope;
938 locals [i].begin_scope = jit->prologue_end;
940 locals [i].end_scope = end_scope;
942 locals [i].end_scope = jit->epilogue_begin;
945 jit->num_locals = header->num_locals;
946 jit->locals = locals;
951 mono_debug_source_location_from_address (MonoMethod *method, guint32 address, guint32 *line_number)
953 MonoDebugMethodInfo *minfo = lookup_method (method);
958 if (minfo->symfile) {
959 gint32 offset = il_offset_from_address (minfo, address);
964 return mono_debug_find_source_location (minfo->symfile, method, offset, line_number);
971 mono_debug_il_offset_from_address (MonoMethod *method, gint32 address)
973 MonoDebugMethodInfo *minfo;
978 minfo = lookup_method (method);
979 if (!minfo || !minfo->il_offsets)
982 return il_offset_from_address (minfo, address);
986 mono_debug_address_from_il_offset (MonoMethod *method, gint32 il_offset)
988 MonoDebugMethodInfo *minfo;
993 minfo = lookup_method (method);
994 if (!minfo || !minfo->il_offsets)
997 return address_from_il_offset (minfo, il_offset);
1001 release_symbol_file_table ()
1005 if (!mono_debugger_symbol_file_table)
1009 * Caution: The debugger may access the memory pointed to by this variable
1010 * at any time. It is very important to set the pointer to NULL
1011 * before freeing the area.
1014 temp = mono_debugger_symbol_file_table;
1015 mono_debugger_symbol_file_table = NULL;
1016 g_free (mono_debugger_symbol_file_table);
1020 mono_debugger_update_symbol_file_table (void)
1022 MonoDebugHandle *debug;
1023 int dirty = 0, count = 0;
1024 guint8 *ptr, *symfiles;
1027 for (debug = mono_debug_handles; debug; debug = debug->next) {
1030 if (debug->format != MONO_DEBUG_FORMAT_MONO)
1036 for (tmp = debug->info; tmp; tmp = tmp->next) {
1037 AssemblyDebugInfo *info = (AssemblyDebugInfo*)tmp->data;
1038 MonoSymbolFile *symfile = info->symfile;
1050 release_symbol_file_table ();
1052 size = 2 * sizeof (guint32) + count * sizeof (MonoSymbolFile);
1053 symfiles = ptr = g_malloc0 (size);
1054 *((guint32 *) ptr)++ = size;
1055 *((guint32 *) ptr)++ = count;
1056 *((guint32 *) ptr)++ = mono_debugger_symbol_file_table_generation;
1058 for (debug = mono_debug_handles; debug; debug = debug->next) {
1061 if (debug->format != MONO_DEBUG_FORMAT_MONO)
1064 for (tmp = debug->info; tmp; tmp = tmp->next) {
1065 AssemblyDebugInfo *info = (AssemblyDebugInfo*)tmp->data;
1066 MonoSymbolFile *symfile = info->symfile;
1072 mono_debug_update_mono_symbol_file (info->symfile);
1074 *((MonoSymbolFile *) ptr)++ = *symfile;
1078 mono_debugger_symbol_file_table = symfiles;