2 #include <mono/metadata/assembly.h>
3 #include <mono/metadata/tabledefs.h>
4 #include <mono/metadata/tokentype.h>
5 #include <mono/metadata/mono-debug.h>
6 #include <mono/metadata/mono-debug-debugger.h>
8 struct _MonoDebugHandlePriv
10 GHashTable *wrapper_info;
11 MonoDebuggerSymbolFile *debugger_info;
14 MonoDebugFormat mono_debug_format;
16 static gboolean in_the_mono_debugger = FALSE;
17 static gboolean mono_debug_initialized = FALSE;
18 GHashTable *mono_debug_handles = NULL;
20 static MonoDebugHandle *mono_debug_open_image (MonoImage *image);
21 static void mono_debug_close_image (MonoDebugHandle *debug);
23 static MonoDebugHandle *_mono_debug_get_image (MonoImage *image);
24 static void mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data);
25 static void mono_debug_add_type (MonoClass *klass);
27 extern void (*mono_debugger_class_init_func) (MonoClass *klass);
30 * Initialize debugging support.
32 * This method must be called after loading corlib,
33 * but before opening the application's main assembly because we need to set some
37 mono_debug_init (MonoDebugFormat format)
41 g_assert (!mono_debug_initialized);
43 mono_debug_initialized = TRUE;
44 mono_debug_format = format;
45 in_the_mono_debugger = format == MONO_DEBUG_FORMAT_DEBUGGER;
47 if (in_the_mono_debugger)
48 mono_debugger_initialize ();
50 mono_debugger_lock ();
52 mono_debug_handles = g_hash_table_new_full
53 (NULL, NULL, NULL, (GDestroyNotify) mono_debug_close_image);
55 mono_debugger_class_init_func = mono_debug_add_type;
56 mono_install_assembly_load_hook (mono_debug_add_assembly, NULL);
58 mono_debug_open_image (mono_defaults.corlib);
59 for (ass = mono_defaults.corlib->references; ass && *ass; ass++)
60 mono_debug_open_image ((*ass)->image);
64 * Initialize debugging support - part 2.
66 * This method must be called after loading the application's main assembly.
69 mono_debug_init_2 (MonoAssembly *assembly)
71 mono_debug_open_image (assembly->image);
73 mono_debug_add_type (mono_defaults.object_class);
74 mono_debug_add_type (mono_defaults.object_class);
75 mono_debug_add_type (mono_defaults.byte_class);
76 mono_debug_add_type (mono_defaults.void_class);
77 mono_debug_add_type (mono_defaults.boolean_class);
78 mono_debug_add_type (mono_defaults.sbyte_class);
79 mono_debug_add_type (mono_defaults.int16_class);
80 mono_debug_add_type (mono_defaults.uint16_class);
81 mono_debug_add_type (mono_defaults.int32_class);
82 mono_debug_add_type (mono_defaults.uint32_class);
83 mono_debug_add_type (mono_defaults.int_class);
84 mono_debug_add_type (mono_defaults.uint_class);
85 mono_debug_add_type (mono_defaults.int64_class);
86 mono_debug_add_type (mono_defaults.uint64_class);
87 mono_debug_add_type (mono_defaults.single_class);
88 mono_debug_add_type (mono_defaults.double_class);
89 mono_debug_add_type (mono_defaults.char_class);
90 mono_debug_add_type (mono_defaults.string_class);
91 mono_debug_add_type (mono_defaults.enum_class);
92 mono_debug_add_type (mono_defaults.array_class);
93 mono_debug_add_type (mono_defaults.multicastdelegate_class);
94 mono_debug_add_type (mono_defaults.asyncresult_class);
95 mono_debug_add_type (mono_defaults.waithandle_class);
96 mono_debug_add_type (mono_defaults.typehandle_class);
97 mono_debug_add_type (mono_defaults.fieldhandle_class);
98 mono_debug_add_type (mono_defaults.methodhandle_class);
99 mono_debug_add_type (mono_defaults.monotype_class);
100 mono_debug_add_type (mono_defaults.exception_class);
101 mono_debug_add_type (mono_defaults.threadabortexception_class);
102 mono_debug_add_type (mono_defaults.thread_class);
103 mono_debug_add_type (mono_defaults.transparent_proxy_class);
104 mono_debug_add_type (mono_defaults.real_proxy_class);
105 mono_debug_add_type (mono_defaults.mono_method_message_class);
106 mono_debug_add_type (mono_defaults.appdomain_class);
107 mono_debug_add_type (mono_defaults.field_info_class);
108 mono_debug_add_type (mono_defaults.stringbuilder_class);
109 mono_debug_add_type (mono_defaults.math_class);
110 mono_debug_add_type (mono_defaults.stack_frame_class);
111 mono_debug_add_type (mono_defaults.stack_trace_class);
112 mono_debug_add_type (mono_defaults.marshal_class);
113 mono_debug_add_type (mono_defaults.iserializeable_class);
114 mono_debug_add_type (mono_defaults.serializationinfo_class);
115 mono_debug_add_type (mono_defaults.streamingcontext_class);
117 mono_debugger_unlock ();
121 mono_debug_cleanup (void)
123 mono_debugger_cleanup ();
125 if (mono_debug_handles)
126 g_hash_table_destroy (mono_debug_handles);
127 mono_debug_handles = NULL;
130 static MonoDebugHandle *
131 _mono_debug_get_image (MonoImage *image)
133 return g_hash_table_lookup (mono_debug_handles, image);
136 static MonoDebugHandle *
137 mono_debug_open_image (MonoImage *image)
139 MonoDebugHandle *handle;
141 handle = _mono_debug_get_image (image);
145 handle = g_new0 (MonoDebugHandle, 1);
146 handle->image = image;
147 handle->image->ref_count++;
148 handle->_priv = g_new0 (MonoDebugHandlePriv, 1);
149 handle->_priv->wrapper_info = g_hash_table_new (g_direct_hash, g_direct_equal);
151 g_hash_table_insert (mono_debug_handles, image, handle);
153 if (image->assembly->dynamic)
156 handle->symfile = mono_debug_open_mono_symbol_file (handle->image, in_the_mono_debugger);
157 if (in_the_mono_debugger)
158 handle->_priv->debugger_info = mono_debugger_add_symbol_file (handle->symfile);
164 mono_debug_close_image (MonoDebugHandle *handle)
167 mono_debug_close_mono_symbol_file (handle->symfile);
168 g_hash_table_destroy (handle->_priv->wrapper_info);
169 handle->image->ref_count--;
170 g_free (handle->_priv);
175 mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data)
177 mono_debugger_lock ();
178 mono_debug_open_image (assembly->image);
179 mono_debugger_unlock ();
183 * This is called via the `mono_debugger_class_init_func' from mono_class_init() each time
184 * a new class is initialized.
187 mono_debug_add_type (MonoClass *klass)
189 MonoDebugHandle *handle;
191 handle = _mono_debug_get_image (klass->image);
194 if (handle->_priv->debugger_info)
195 mono_debugger_add_type (handle->_priv->debugger_info, klass);
198 struct LookupMethodData
200 MonoDebugMethodInfo *minfo;
205 lookup_method_func (gpointer key, gpointer value, gpointer user_data)
207 MonoDebugHandle *handle = (MonoDebugHandle *) value;
208 struct LookupMethodData *data = (struct LookupMethodData *) user_data;
214 data->minfo = mono_debug_find_method (handle->symfile, data->method);
217 static MonoDebugMethodInfo *
218 _mono_debug_lookup_method (MonoMethod *method)
220 struct LookupMethodData data = { NULL, method };
222 if (!mono_debug_handles)
225 g_hash_table_foreach (mono_debug_handles, lookup_method_func, &data);
230 * This is called by the JIT to tell the debugging code about a newly compiled
234 mono_debug_add_wrapper (MonoMethod *method, MonoMethod *wrapper_method)
236 MonoClass *klass = method->klass;
237 MonoDebugHandle *handle;
238 MonoDebugMethodInfo *minfo;
239 MonoDebugMethodJitInfo *jit;
241 if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
244 mono_class_init (klass);
246 handle = _mono_debug_get_image (klass->image);
249 minfo = _mono_debug_lookup_method (method);
250 if (!minfo || minfo->jit)
253 jit = g_hash_table_lookup (handle->_priv->wrapper_info, wrapper_method);
256 mono_debugger_lock ();
259 minfo->jit->wrapper_addr = method->addr;
261 if (handle->_priv->debugger_info)
262 mono_debugger_add_method (handle->_priv->debugger_info, method);
264 mono_debugger_unlock ();
268 * This is called by the JIT to tell the debugging code about a newly
272 mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit)
274 MonoClass *klass = method->klass;
275 MonoDebugHandle *handle;
276 MonoDebugMethodInfo *minfo;
278 mono_class_init (klass);
280 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
281 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
282 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
283 (method->flags & METHOD_ATTRIBUTE_ABSTRACT))
286 handle = _mono_debug_get_image (klass->image);
289 if (method->wrapper_type != MONO_WRAPPER_NONE) {
290 g_hash_table_insert (handle->_priv->wrapper_info, method, jit);
294 minfo = _mono_debug_lookup_method (method);
298 mono_debugger_lock ();
300 g_assert (!minfo->jit);
303 if (handle->_priv->debugger_info)
304 mono_debugger_add_method (handle->_priv->debugger_info, method);
306 mono_debugger_unlock ();
310 il_offset_from_address (MonoDebugMethodInfo *minfo, guint32 address)
314 if (!minfo->jit || !minfo->jit->line_numbers)
317 for (i = minfo->jit->line_numbers->len - 1; i >= 0; i--) {
318 MonoDebugLineNumberEntry lne = g_array_index (
319 minfo->jit->line_numbers, MonoDebugLineNumberEntry, i);
321 if (lne.address <= address)
329 * Used by the exception code to get a source location from a machine address.
331 * Returns a textual representation of the specified address which is suitable to be displayed to
332 * the user (for instance "/home/martin/monocvs/debugger/test/Y.cs:8").
334 * If the optional @line_number argument is not NULL, the line number is stored there and just the
335 * source file is returned (ie. it'd return "/home/martin/monocvs/debugger/test/Y.cs" and store the
336 * line number 8 in the variable pointed to by @line_number).
339 mono_debug_source_location_from_address (MonoMethod *method, guint32 address, guint32 *line_number)
341 MonoDebugMethodInfo *minfo = _mono_debug_lookup_method (method);
346 if (minfo->symfile) {
347 gint32 offset = il_offset_from_address (minfo, address);
352 return mono_debug_find_source_location (minfo->symfile, method, offset, line_number);
359 * Used by the exception code to get a source location from an IL offset.
361 * Returns a textual representation of the specified address which is suitable to be displayed to
362 * the user (for instance "/home/martin/monocvs/debugger/test/Y.cs:8").
364 * If the optional @line_number argument is not NULL, the line number is stored there and just the
365 * source file is returned (ie. it'd return "/home/martin/monocvs/debugger/test/Y.cs" and store the
366 * line number 8 in the variable pointed to by @line_number).
369 mono_debug_source_location_from_il_offset (MonoMethod *method, guint32 offset, guint32 *line_number)
371 MonoDebugMethodInfo *minfo = _mono_debug_lookup_method (method);
373 if (!minfo || !minfo->symfile)
376 return mono_debug_find_source_location (minfo->symfile, method, offset, line_number);
380 * Returns the IL offset corresponding to machine address @address which is an offset
381 * relative to the beginning of the method @method.
384 mono_debug_il_offset_from_address (MonoMethod *method, gint32 address)
386 MonoDebugMethodInfo *minfo;
391 minfo = _mono_debug_lookup_method (method);
392 if (!minfo || !minfo->il_offsets)
395 return il_offset_from_address (minfo, address);
399 * Returns the machine address corresponding to IL offset @il_offset.
400 * The returned value is an offset relative to the beginning of the method @method.
403 mono_debug_address_from_il_offset (MonoMethod *method, gint32 il_offset)
405 MonoDebugMethodInfo *minfo;
410 minfo = _mono_debug_lookup_method (method);
411 if (!minfo || !minfo->il_offsets)
414 return _mono_debug_address_from_il_offset (minfo, il_offset);