8 #include <mono/metadata/class.h>
9 #include <mono/metadata/assembly.h>
10 #include <mono/metadata/tabledefs.h>
11 #include <mono/metadata/tokentype.h>
12 #include <mono/metadata/debug-helpers.h>
13 #include <mono/metadata/debug-mono-symfile.h>
15 #include "debug-private.h"
18 * NOTE: Functions and variables starting with `mono_debug_' and `debug_' are
19 * part of the general debugging code.
21 * Functions and variables starting with `mono_debugger_' and `debugger_'
22 * are only used when the JIT is running inside the Mono Debugger.
24 * FIXME: This file needs some API loving.
27 /* This is incremented each time the symbol table is modified.
28 * The debugger looks at this variable and if it has a higher value than its current
29 * copy of the symbol table, it must call mono_debug_update_symbol_file_table().
31 guint32 mono_debugger_symbol_file_table_generation = 0;
32 guint32 mono_debugger_symbol_file_table_modified = 0;
34 /* Caution: This variable may be accessed at any time from the debugger;
35 * it is very important not to modify the memory it is pointing to
36 * without previously setting this pointer back to NULL.
38 MonoDebuggerSymbolFileTable *mono_debugger_symbol_file_table = NULL;
40 /* Caution: This function MUST be called before touching the symbol table! */
41 static void release_symbol_file_table (void);
43 MonoDebugHandle *mono_debug_handle = NULL;
44 gboolean mono_debug_initialized = FALSE;
46 static CRITICAL_SECTION debugger_lock_mutex;
48 extern void (*mono_debugger_class_init_func) (MonoClass *klass);
50 static void mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data);
51 static void mono_debug_close_assembly (AssemblyDebugInfo* info);
52 static AssemblyDebugInfo *mono_debug_open_image (MonoDebugHandle* debug, MonoImage *image);
54 static int running_in_the_mono_debugger = FALSE;
55 void (*mono_debugger_event_handler) (MonoDebuggerEvent event, gpointer data, gpointer data2) = NULL;
57 #ifndef PLATFORM_WIN32
59 MonoDebuggerIOLayer mono_debugger_io_layer = {
60 InitializeCriticalSection, DeleteCriticalSection, TryEnterCriticalSection,
61 EnterCriticalSection, LeaveCriticalSection, WaitForSingleObject, SignalObjectAndWait,
62 WaitForMultipleObjects, CreateSemaphore, ReleaseSemaphore, CreateThread
68 mono_debugger_event (MonoDebuggerEvent event, gpointer data, gpointer data2)
70 if (mono_debugger_event_handler)
71 (* mono_debugger_event_handler) (event, data, data2);
75 mono_debug_init (int in_the_debugger)
77 if (mono_debug_initialized)
80 InitializeCriticalSection (&debugger_lock_mutex);
81 mono_debug_initialized = TRUE;
82 running_in_the_mono_debugger = in_the_debugger;
86 mono_debug_create_notification_function (gpointer *notification_address)
90 ptr = buf = g_malloc0 (16);
91 mono_debug_codegen_breakpoint (&buf);
92 if (notification_address)
93 *notification_address = buf;
94 mono_debug_codegen_ret (&buf);
100 mono_debug_lock (void)
102 if (mono_debug_initialized)
103 EnterCriticalSection (&debugger_lock_mutex);
107 mono_debug_unlock (void)
109 if (mono_debug_initialized)
110 LeaveCriticalSection (&debugger_lock_mutex);
114 free_method_info (MonoDebugMethodInfo *minfo)
116 DebugMethodInfo *priv = minfo->user_data;
124 g_array_free (minfo->jit->line_numbers, TRUE);
125 g_free (minfo->jit->this_var);
126 g_free (minfo->jit->params);
127 g_free (minfo->jit->locals);
131 g_free (minfo->il_offsets);
136 free_wrapper_info (DebugWrapperInfo *winfo)
142 debug_arg_warning (const char *message)
144 g_warning ("Error while processing --debug-args arguments: %s", message);
148 mono_debug_open (MonoAssembly *assembly, MonoDebugFormat format, const char **args)
150 MonoDebugHandle *debug;
153 g_assert (!mono_debug_handle);
155 debug = g_new0 (MonoDebugHandle, 1);
156 debug->name = g_strdup (assembly->image->name);
157 debug->format = format;
158 debug->source_files = g_ptr_array_new ();
159 debug->producer_name = g_strdup_printf ("Mono JIT compiler version %s", VERSION);
160 debug->next_idx = 100;
163 debug->type_hash = g_hash_table_new (NULL, NULL);
165 debug->images = g_hash_table_new_full (NULL, NULL, NULL,
166 (GDestroyNotify) mono_debug_close_assembly);
168 for (ptr = args; ptr && *ptr; ptr++) {
169 const char *arg = *ptr;
172 switch (debug->format) {
173 case MONO_DEBUG_FORMAT_STABS:
174 case MONO_DEBUG_FORMAT_DWARF2:
175 if (!strncmp (arg, "filename=", 9)) {
177 debug_arg_warning ("The `filename' argument can be given only once.");
178 debug->filename = g_strdup (arg + 9);
180 } else if (!strncmp (arg, "objfile=", 8)) {
182 debug_arg_warning ("The `objfile' argument can be given only once.");
183 debug->objfile = g_strdup (arg + 8);
187 case MONO_DEBUG_FORMAT_MONO:
188 debug->flags |= MONO_DEBUG_FLAGS_DONT_UPDATE_IL_FILES |
189 MONO_DEBUG_FLAGS_DONT_CREATE_IL_FILES;
195 if (debug->format != MONO_DEBUG_FORMAT_MONO) {
196 if (!strcmp (arg, "dont_assemble")) {
197 debug->flags |= MONO_DEBUG_FLAGS_DONT_ASSEMBLE;
199 } else if (!strcmp (arg, "update_on_exit")) {
200 debug->flags |= MONO_DEBUG_FLAGS_UPDATE_ON_EXIT;
202 } else if (!strcmp (arg, "install_il_files")) {
203 debug->flags |= MONO_DEBUG_FLAGS_INSTALL_IL_FILES;
205 } else if (!strcmp (arg, "dont_update_il_files")) {
206 debug->flags |= MONO_DEBUG_FLAGS_DONT_UPDATE_IL_FILES;
208 } else if (!strcmp (arg, "dont_create_il_files")) {
209 debug->flags |= MONO_DEBUG_FLAGS_DONT_CREATE_IL_FILES;
214 message = g_strdup_printf ("Unknown argument `%s'.", arg);
215 debug_arg_warning (message);
219 switch (debug->format) {
220 case MONO_DEBUG_FORMAT_STABS:
221 if (!debug->filename)
222 debug->filename = g_strdup_printf ("%s-stabs.s", g_basename (debug->name));
224 debug->objfile = g_strdup_printf ("%s.o", g_basename (debug->name));
226 case MONO_DEBUG_FORMAT_DWARF2:
227 if (!debug->filename)
228 debug->filename = g_strdup_printf ("%s-dwarf.s", g_basename (debug->name));
230 debug->objfile = g_strdup_printf ("%s.o", g_basename (debug->name));
232 case MONO_DEBUG_FORMAT_MONO:
233 mono_debugger_class_init_func = mono_debug_add_type;
236 g_assert_not_reached ();
240 release_symbol_file_table ();
242 mono_debug_handle = debug;
243 mono_install_assembly_load_hook (mono_debug_add_assembly, NULL);
245 mono_debug_open_image (mono_debug_handle, assembly->image);
246 mono_debug_open_image (mono_debug_handle, mono_defaults.corlib);
248 mono_debug_add_type (mono_defaults.object_class);
249 mono_debug_add_type (mono_defaults.object_class);
250 mono_debug_add_type (mono_defaults.byte_class);
251 mono_debug_add_type (mono_defaults.void_class);
252 mono_debug_add_type (mono_defaults.boolean_class);
253 mono_debug_add_type (mono_defaults.sbyte_class);
254 mono_debug_add_type (mono_defaults.int16_class);
255 mono_debug_add_type (mono_defaults.uint16_class);
256 mono_debug_add_type (mono_defaults.int32_class);
257 mono_debug_add_type (mono_defaults.uint32_class);
258 mono_debug_add_type (mono_defaults.int_class);
259 mono_debug_add_type (mono_defaults.uint_class);
260 mono_debug_add_type (mono_defaults.int64_class);
261 mono_debug_add_type (mono_defaults.uint64_class);
262 mono_debug_add_type (mono_defaults.single_class);
263 mono_debug_add_type (mono_defaults.double_class);
264 mono_debug_add_type (mono_defaults.char_class);
265 mono_debug_add_type (mono_defaults.string_class);
266 mono_debug_add_type (mono_defaults.enum_class);
267 mono_debug_add_type (mono_defaults.array_class);
268 mono_debug_add_type (mono_defaults.multicastdelegate_class);
269 mono_debug_add_type (mono_defaults.asyncresult_class);
270 mono_debug_add_type (mono_defaults.waithandle_class);
271 mono_debug_add_type (mono_defaults.typehandle_class);
272 mono_debug_add_type (mono_defaults.fieldhandle_class);
273 mono_debug_add_type (mono_defaults.methodhandle_class);
274 mono_debug_add_type (mono_defaults.monotype_class);
275 mono_debug_add_type (mono_defaults.exception_class);
276 mono_debug_add_type (mono_defaults.threadabortexception_class);
277 mono_debug_add_type (mono_defaults.thread_class);
278 mono_debug_add_type (mono_defaults.transparent_proxy_class);
279 mono_debug_add_type (mono_defaults.real_proxy_class);
280 mono_debug_add_type (mono_defaults.mono_method_message_class);
281 mono_debug_add_type (mono_defaults.appdomain_class);
282 mono_debug_add_type (mono_defaults.field_info_class);
283 mono_debug_add_type (mono_defaults.stringbuilder_class);
284 mono_debug_add_type (mono_defaults.math_class);
285 mono_debug_add_type (mono_defaults.stack_frame_class);
286 mono_debug_add_type (mono_defaults.stack_trace_class);
287 mono_debug_add_type (mono_defaults.marshal_class);
288 mono_debug_add_type (mono_defaults.iserializeable_class);
289 mono_debug_add_type (mono_defaults.serializationinfo_class);
290 mono_debug_add_type (mono_defaults.streamingcontext_class);
292 mono_debug_update_symbol_file_table ();
294 mono_debug_unlock ();
300 mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data)
302 if (!mono_debug_handle)
306 mono_debug_open_image (mono_debug_handle, assembly->image);
307 mono_debug_unlock ();
311 generate_il_offsets (AssemblyDebugInfo *info, MonoMethod *method)
313 GPtrArray *il_offsets = g_ptr_array_new ();
314 MonoClass *klass = method->klass;
315 MonoDebugMethodInfo *minfo;
316 DebugMethodInfo *priv;
319 g_assert (klass->image == info->image);
321 /* FIXME: doesn't work yet. */
322 if (!strcmp (klass->name_space, "System.Runtime.Remoting.Proxies"))
325 mono_class_init (klass);
327 minfo = g_new0 (MonoDebugMethodInfo, 1);
328 minfo->method = method;
329 minfo->user_data = priv = g_new0 (DebugMethodInfo, 1);
331 priv->name = g_strdup_printf ("%s%s%s.%s", klass->name_space, klass->name_space [0]? ".": "",
332 klass->name, method->name);
333 priv->source_file = info->source_file;
337 * Find the method index in the image.
339 for (i = 0; klass->methods && i < klass->method.count; ++i) {
340 if (klass->methods [i] == minfo->method) {
341 priv->method_number = klass->method.first + i + 1;
342 priv->first_line = info->mlines [priv->method_number];
347 g_assert (priv->method_number);
349 /* info->moffsets contains -1 "outside" of functions. */
350 for (i = priv->first_line; (i > 0) && (info->moffsets [i] == 0); i--)
352 priv->start_line = i + 1;
354 for (i = priv->start_line; info->moffsets [i] != -1; i++) {
355 MonoSymbolFileLineNumberEntry *lne = g_new0 (MonoSymbolFileLineNumberEntry, 1);
357 if (!info->moffsets [i] && (i > priv->start_line))
360 lne->offset = info->moffsets [i];
363 g_ptr_array_add (il_offsets, lne);
368 minfo->start_line = priv->first_line;
369 minfo->end_line = priv->last_line;
371 minfo->num_il_offsets = il_offsets->len;
372 minfo->il_offsets = g_new0 (MonoSymbolFileLineNumberEntry, il_offsets->len);
373 for (i = 0; i < il_offsets->len; i++) {
374 MonoSymbolFileLineNumberEntry *il = g_ptr_array_index (il_offsets, i);
376 minfo->il_offsets [i] = *il;
379 g_ptr_array_free (il_offsets, TRUE);
381 g_hash_table_insert (info->methods, method, minfo);
385 debug_load_method_lines (AssemblyDebugInfo* info)
387 MonoTableInfo *table = &info->image->tables [MONO_TABLE_METHOD];
393 if (info->always_create_il || !(info->handle->flags & MONO_DEBUG_FLAGS_DONT_UPDATE_IL_FILES)) {
394 char *command = g_strdup_printf ("monodis --output=%s %s",
395 info->ilfile, info->image->name);
396 struct stat stata, statb;
397 int need_update = FALSE;
399 if (stat (info->image->name, &stata)) {
400 g_warning ("cannot access assembly file (%s): %s",
401 info->image->name, g_strerror (errno));
406 /* If the stat() failed or the file is older. */
407 if (stat (info->ilfile, &statb)) {
409 } else if (statb.st_mtime < stata.st_mtime)
413 #ifndef PLATFORM_WIN32
414 struct sigaction act, oldact;
419 #ifndef PLATFORM_WIN32
420 act.sa_handler = SIG_IGN;
421 act.sa_flags = SA_NOCLDSTOP | SA_RESTART;
422 sigemptyset (&act.sa_mask);
423 sigaddset (&act.sa_mask, SIGCHLD);
424 sigprocmask (SIG_BLOCK, &act.sa_mask, &old_set);
425 sigaction (SIGCHLD, &act, &oldact);
428 g_print ("Recreating %s from %s.\n", info->ilfile, info->image->name);
430 ret = system (command);
432 #ifndef PLATFORM_WIN32
433 sigaction (SIGCHLD, &oldact, NULL);
434 sigprocmask (SIG_SETMASK, &old_set, NULL);
438 g_warning ("cannot create IL assembly file (%s): %s",
439 command, g_strerror (errno));
446 /* use an env var with directories for searching. */
447 if (!(f = fopen (info->ilfile, "r"))) {
448 g_warning ("cannot open IL assembly file %s", info->ilfile);
452 info->total_lines = 100;
453 info->moffsets = g_malloc (info->total_lines * sizeof (int));
456 while (fgets (buf, sizeof (buf), f)) {
459 info->moffsets [i++] = offset;
460 if (i + 2 >= info->total_lines) {
461 info->total_lines += 100;
462 info->moffsets = g_realloc (info->moffsets, info->total_lines * sizeof (int));
463 g_assert (info->moffsets);
466 if (!sscanf (buf, " // method line %d", &mnum))
471 if (mnum >= info->nmethods)
474 while (fgets (buf, sizeof (buf), f)) {
478 if (i + 2 >= info->total_lines) {
479 info->total_lines += 100;
480 info->moffsets = g_realloc (info->moffsets, info->total_lines * sizeof (int));
481 g_assert (info->moffsets);
484 if (strstr (buf, "}")) {
489 if (sscanf (buf, " IL_%x:", &newoffset)) {
495 info->moffsets [i] = offset;
497 /* g_print ("method %d found at %d\n", mnum, pos); */
498 info->mlines [mnum] = pos;
502 for (idx = 1; idx <= table->rows; idx++) {
503 guint32 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
504 MonoMethod *method = mono_get_method (info->image, token, NULL);
506 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
507 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
508 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
511 if (method->wrapper_type != MONO_WRAPPER_NONE)
514 generate_il_offsets (info, method);
519 _mono_debug_generate_line_number (MonoDebugMethodInfo *minfo, guint32 address, guint32 offset, int debug)
524 g_message (G_STRLOC ": searching IL offset %x", offset);
526 for (i = minfo->num_il_offsets - 1; i >= 0; i--) {
527 MonoDebugLineNumberEntry *lne;
529 if (minfo->il_offsets [i].offset > offset)
533 g_message (G_STRLOC ": found entry %d: offset = %x, row = %d",
534 i, minfo->il_offsets [i].offset, minfo->il_offsets [i].row);
536 if (minfo->jit->line_numbers->len) {
537 MonoDebugLineNumberEntry last = g_array_index (
538 minfo->jit->line_numbers, MonoDebugLineNumberEntry,
539 minfo->jit->line_numbers->len - 1);
541 /* Avoid writing more than one entry for the same line. */
542 if (minfo->il_offsets [i].row == last.line) {
544 g_message (G_STRLOC ": skipping line: line = %d, last line = %d, "
545 "last address = %x, address = %x, "
546 "last offset = %x, offset = %x",
547 last.line, minfo->il_offsets [i].row,
548 last.address, address, last.offset, offset);
555 g_message (G_STRLOC ": writing entry: line = %d, offfset = %x, address = %x",
556 minfo->il_offsets [i].row, offset, address);
558 lne = g_new0 (MonoDebugLineNumberEntry, 1);
559 lne->address = address;
560 lne->offset = offset;
561 lne->line = minfo->il_offsets [i].row;
563 g_array_append_val (minfo->jit->line_numbers, *lne);
569 _mono_debug_get_image (MonoDebugHandle* debug, MonoImage *image)
571 return g_hash_table_lookup (debug->images, image);
574 static AssemblyDebugInfo *
575 mono_debug_open_image (MonoDebugHandle* debug, MonoImage *image)
577 AssemblyDebugInfo *info;
580 info = _mono_debug_get_image (debug, image);
586 info = g_new0 (AssemblyDebugInfo, 1);
588 info->image->ref_count++;
589 info->name = g_strdup (image->assembly_name);
590 info->format = debug->format;
591 info->handle = debug;
592 info->methods = g_hash_table_new_full (g_direct_hash, g_direct_equal,
593 NULL, (GDestroyNotify) free_method_info);
594 info->wrapper_methods = g_hash_table_new_full (g_direct_hash, g_direct_equal,
595 NULL, (GDestroyNotify) free_wrapper_info);
597 g_hash_table_insert (debug->images, image, info);
599 info->nmethods = image->tables [MONO_TABLE_METHOD].rows + 1;
600 info->mlines = g_new0 (int, info->nmethods);
602 for (ptr = image->references; ptr && *ptr; ptr++)
603 mono_debug_add_assembly (*ptr, NULL);
605 if (image->assembly->dynamic)
608 switch (info->format) {
609 case MONO_DEBUG_FORMAT_STABS:
610 case MONO_DEBUG_FORMAT_DWARF2:
611 if (debug->flags & MONO_DEBUG_FLAGS_INSTALL_IL_FILES) {
612 gchar *dirname = g_path_get_dirname (image->name);
613 info->ilfile = g_strdup_printf ("%s/%s.il", dirname, info->name);
616 info->ilfile = g_strdup_printf ("%s.il", info->name);
617 info->source_file = debug->source_files->len;
618 g_ptr_array_add (debug->source_files, info->ilfile);
620 case MONO_DEBUG_FORMAT_MONO:
621 info->symfile = mono_debug_open_mono_symbol_file (info->image, running_in_the_mono_debugger);
622 mono_debugger_symbol_file_table_generation++;
629 if (debug->format != MONO_DEBUG_FORMAT_MONO)
630 debug_load_method_lines (info);
636 mono_debug_write_symbols (MonoDebugHandle *debug)
638 if (!debug || !debug->dirty)
641 release_symbol_file_table ();
643 switch (debug->format) {
644 case MONO_DEBUG_FORMAT_STABS:
645 mono_debug_write_stabs (debug);
647 case MONO_DEBUG_FORMAT_DWARF2:
648 mono_debug_write_dwarf2 (debug);
650 case MONO_DEBUG_FORMAT_MONO:
653 g_assert_not_reached ();
656 debug->dirty = FALSE;
660 mono_debug_make_symbols (void)
662 if (!mono_debug_handle || !mono_debug_handle->dirty)
665 switch (mono_debug_handle->format) {
666 case MONO_DEBUG_FORMAT_STABS:
667 mono_debug_write_stabs (mono_debug_handle);
669 case MONO_DEBUG_FORMAT_DWARF2:
670 mono_debug_write_dwarf2 (mono_debug_handle);
672 case MONO_DEBUG_FORMAT_MONO:
673 mono_debug_update_symbol_file_table ();
676 g_assert_not_reached ();
679 mono_debug_handle->dirty = FALSE;
683 mono_debug_close_assembly (AssemblyDebugInfo* info)
685 switch (info->format) {
686 case MONO_DEBUG_FORMAT_MONO:
687 if (info->symfile != NULL)
688 mono_debug_close_mono_symbol_file (info->symfile);
693 g_hash_table_destroy (info->methods);
694 g_hash_table_destroy (info->wrapper_methods);
695 g_free (info->mlines);
696 g_free (info->moffsets);
698 g_free (info->ilfile);
699 g_free (info->filename);
700 g_free (info->objfile);
705 mono_debug_cleanup (void)
707 release_symbol_file_table ();
709 if (!mono_debug_handle)
712 if (mono_debug_handle->flags & MONO_DEBUG_FLAGS_UPDATE_ON_EXIT)
713 mono_debug_write_symbols (mono_debug_handle);
715 g_hash_table_destroy (mono_debug_handle->images);
716 g_ptr_array_free (mono_debug_handle->source_files, FALSE);
717 g_hash_table_destroy (mono_debug_handle->type_hash);
718 g_free (mono_debug_handle->producer_name);
719 g_free (mono_debug_handle->name);
720 g_free (mono_debug_handle);
722 mono_debug_handle = NULL;
726 mono_debug_get_type (MonoDebugHandle *debug, MonoClass *klass)
730 mono_class_init (klass);
732 index = GPOINTER_TO_INT (g_hash_table_lookup (debug->type_hash, klass));
738 index = ++debug->next_klass_idx;
739 g_hash_table_insert (debug->type_hash, klass, GINT_TO_POINTER (index));
744 switch (klass->byval_arg.type) {
745 case MONO_TYPE_CLASS:
747 mono_debug_get_type (debug, klass->parent);
749 for (i = 0; i < klass->method.count; i++) {
750 MonoMethod *method = klass->methods [i];
751 MonoType *ret_type = NULL;
754 if (method->signature->ret->type != MONO_TYPE_VOID)
755 ret_type = method->signature->ret;
758 MonoClass *ret_klass = mono_class_from_mono_type (ret_type);
759 mono_debug_get_type (debug, ret_klass);
762 for (j = 0; j < method->signature->param_count; j++) {
763 MonoType *sub_type = method->signature->params [j];
764 MonoClass *sub_klass = mono_class_from_mono_type (sub_type);
765 mono_debug_get_type (debug, sub_klass);
769 case MONO_TYPE_VALUETYPE:
770 for (i = 0; i < klass->field.count; i++) {
771 MonoClass *subclass = mono_class_from_mono_type (klass->fields [i].type);
772 mono_debug_get_type (debug, subclass);
775 case MONO_TYPE_ARRAY:
776 case MONO_TYPE_SZARRAY:
777 mono_debug_get_type (debug, klass->element_class);
787 il_offset_from_address (MonoDebugMethodInfo *minfo, guint32 address)
791 if (!minfo->jit || !minfo->jit->line_numbers)
794 for (i = minfo->jit->line_numbers->len - 1; i >= 0; i--) {
795 MonoDebugLineNumberEntry lne = g_array_index (
796 minfo->jit->line_numbers, MonoDebugLineNumberEntry, i);
798 if (lne.address <= address)
806 _mono_debug_address_from_il_offset (MonoDebugMethodInfo *minfo, guint32 il_offset)
810 if (!minfo->jit || !minfo->jit->line_numbers)
813 for (i = minfo->jit->line_numbers->len - 1; i >= 0; i--) {
814 MonoDebugLineNumberEntry lne = g_array_index (
815 minfo->jit->line_numbers, MonoDebugLineNumberEntry, i);
817 if (lne.offset <= il_offset)
825 mono_debug_add_type (MonoClass *klass)
827 AssemblyDebugInfo* info;
829 if (!mono_debug_handle)
832 info = _mono_debug_get_image (mono_debug_handle, klass->image);
835 if (mono_debug_handle->format != MONO_DEBUG_FORMAT_MONO)
840 mono_debug_symfile_add_type (info->symfile, klass);
841 mono_debugger_event (MONO_DEBUGGER_EVENT_TYPE_ADDED, info->symfile, klass);
842 mono_debug_unlock ();
846 struct LookupMethodData
848 MonoDebugMethodInfo *minfo;
853 lookup_method_func (gpointer key, gpointer value, gpointer user_data)
855 AssemblyDebugInfo *info = (AssemblyDebugInfo *) value;
856 struct LookupMethodData *data = (struct LookupMethodData *) user_data;
862 data->minfo = mono_debug_find_method (info->symfile, data->method);
864 data->minfo = g_hash_table_lookup (info->methods, data->method);
867 MonoDebugMethodInfo *
868 _mono_debug_lookup_method (MonoMethod *method)
870 struct LookupMethodData data = { NULL, method };
872 if (!mono_debug_handle)
875 g_hash_table_foreach (mono_debug_handle->images, lookup_method_func, &data);
880 mono_debug_add_wrapper (MonoMethod *method, MonoMethod *wrapper_method)
882 MonoClass *klass = method->klass;
883 AssemblyDebugInfo* info;
884 MonoDebugMethodInfo *minfo;
885 DebugWrapperInfo *winfo;
886 MonoDebugMethodJitInfo *jit;
888 if (!mono_debug_handle)
891 if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
894 mono_class_init (klass);
896 info = _mono_debug_get_image (mono_debug_handle, klass->image);
899 minfo = _mono_debug_lookup_method (method);
900 if (!minfo || minfo->jit)
903 winfo = g_hash_table_lookup (info->wrapper_methods, wrapper_method);
908 mono_debug_handle->dirty = TRUE;
910 minfo->jit = jit = g_new0 (MonoDebugMethodJitInfo, 1);
911 jit->code_start = winfo->code_start;
912 jit->code_size = winfo->code_size;
913 jit->prologue_end = 0;
914 jit->epilogue_begin = winfo->code_size;
916 jit->wrapper_addr = method->addr;
919 mono_debug_symfile_add_method (info->symfile, method);
920 mono_debugger_event (MONO_DEBUGGER_EVENT_METHOD_ADDED, info->symfile, method);
923 mono_debug_unlock ();
927 mono_debug_source_location_from_address (MonoMethod *method, guint32 address, guint32 *line_number)
929 MonoDebugMethodInfo *minfo = _mono_debug_lookup_method (method);
934 if (minfo->symfile) {
935 gint32 offset = il_offset_from_address (minfo, address);
940 return mono_debug_find_source_location (minfo->symfile, method, offset, line_number);
947 mono_debug_il_offset_from_address (MonoMethod *method, gint32 address)
949 MonoDebugMethodInfo *minfo;
954 minfo = _mono_debug_lookup_method (method);
955 if (!minfo || !minfo->il_offsets)
958 return il_offset_from_address (minfo, address);
962 mono_debug_address_from_il_offset (MonoMethod *method, gint32 il_offset)
964 MonoDebugMethodInfo *minfo;
969 minfo = _mono_debug_lookup_method (method);
970 if (!minfo || !minfo->il_offsets)
973 return _mono_debug_address_from_il_offset (minfo, il_offset);
977 release_symbol_file_table ()
979 MonoDebuggerSymbolFileTable *temp;
981 if (!mono_debugger_symbol_file_table)
985 * Caution: The debugger may access the memory pointed to by this variable
986 * at any time. It is very important to set the pointer to NULL
987 * before freeing the area.
990 temp = mono_debugger_symbol_file_table;
991 mono_debugger_symbol_file_table = NULL;
992 g_free (mono_debugger_symbol_file_table);
996 update_symbol_file_table_count_func (gpointer key, gpointer value, gpointer user_data)
998 AssemblyDebugInfo *info = (AssemblyDebugInfo *) value;
1002 if (info->format != MONO_DEBUG_FORMAT_MONO)
1005 ++ (* (int *) user_data);
1008 struct SymfileTableData
1010 MonoDebuggerSymbolFileTable *symfile_table;
1015 update_symbol_file_table_func (gpointer key, gpointer value, gpointer user_data)
1017 AssemblyDebugInfo *info = (AssemblyDebugInfo *) value;
1018 struct SymfileTableData *data = (struct SymfileTableData *) user_data;
1022 if (info->format != MONO_DEBUG_FORMAT_MONO)
1025 data->symfile_table->symfiles [data->index++] = info->symfile;
1029 mono_debug_update_symbol_file_table (void)
1032 MonoDebuggerSymbolFileTable *symfile_table;
1033 struct SymfileTableData data;
1036 if (!mono_debug_handle)
1041 g_hash_table_foreach (mono_debug_handle->images, update_symbol_file_table_count_func, &count);
1043 release_symbol_file_table ();
1045 size = sizeof (MonoDebuggerSymbolFileTable) + count * sizeof (MonoSymbolFile *);
1046 symfile_table = g_malloc0 (size);
1047 symfile_table->magic = MONO_SYMBOL_FILE_DYNAMIC_MAGIC;
1048 symfile_table->version = MONO_SYMBOL_FILE_DYNAMIC_VERSION;
1049 symfile_table->total_size = size;
1050 symfile_table->count = count;
1051 symfile_table->generation = mono_debugger_symbol_file_table_generation;
1052 symfile_table->global_symfile = mono_debugger_global_symbol_file;
1054 data.symfile_table = symfile_table;
1057 g_hash_table_foreach (mono_debug_handle->images, update_symbol_file_table_func, &data);
1059 mono_debugger_symbol_file_table = symfile_table;
1061 mono_debug_unlock ();
1066 static GPtrArray *breakpoints = NULL;
1069 mono_insert_breakpoint_full (MonoMethodDesc *desc, gboolean use_trampoline)
1071 static int last_breakpoint_id = 0;
1072 MonoDebuggerBreakpointInfo *info;
1074 info = g_new0 (MonoDebuggerBreakpointInfo, 1);
1076 info->use_trampoline = use_trampoline;
1077 info->index = ++last_breakpoint_id;
1080 breakpoints = g_ptr_array_new ();
1082 g_ptr_array_add (breakpoints, info);
1088 mono_remove_breakpoint (int breakpoint_id)
1095 for (i = 0; i < breakpoints->len; i++) {
1096 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
1098 if (info->index != breakpoint_id)
1101 mono_method_desc_free (info->desc);
1102 g_ptr_array_remove (breakpoints, info);
1111 mono_insert_breakpoint (const gchar *method_name, gboolean include_namespace)
1113 MonoMethodDesc *desc;
1115 desc = mono_method_desc_new (method_name, include_namespace);
1119 return mono_insert_breakpoint_full (desc, running_in_the_mono_debugger);
1123 mono_method_has_breakpoint (MonoMethod* method, gboolean use_trampoline)
1127 if (!breakpoints || (method->wrapper_type != MONO_WRAPPER_NONE))
1130 for (i = 0; i < breakpoints->len; i++) {
1131 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
1133 if (info->use_trampoline != use_trampoline)
1136 if (!mono_method_desc_full_match (info->desc, method))
1146 mono_debugger_trampoline_breakpoint_callback (void)
1148 mono_debugger_event (MONO_DEBUGGER_EVENT_BREAKPOINT_TRAMPOLINE, NULL, NULL);