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/mono-debug.h>
7 #include <mono/metadata/mono-debug-debugger.h>
9 struct _MonoDebugHandlePriv
11 MonoDebuggerSymbolFile *debugger_info;
12 MonoDebugDomainData *domain_table;
15 struct _MonoDebugDomainDataPriv
17 GHashTable *wrapper_info;
18 MonoDebugDomainData *next;
21 MonoDebugFormat mono_debug_format = MONO_DEBUG_FORMAT_NONE;
23 static gboolean in_the_mono_debugger = FALSE;
24 static gboolean mono_debug_initialized = FALSE;
25 GHashTable *mono_debug_handles = NULL;
27 static MonoDebugHandle *mono_debug_open_image (MonoImage *image);
28 static void mono_debug_close_image (MonoDebugHandle *debug);
30 static MonoDebugHandle *_mono_debug_get_image (MonoImage *image);
31 static void mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data);
32 static void mono_debug_add_type (MonoClass *klass);
34 extern void (*mono_debugger_class_init_func) (MonoClass *klass);
37 * Initialize debugging support.
39 * This method must be called after loading corlib,
40 * but before opening the application's main assembly because we need to set some
44 mono_debug_init (MonoDebugFormat format)
48 g_assert (!mono_debug_initialized);
50 mono_debug_initialized = TRUE;
51 mono_debug_format = format;
52 in_the_mono_debugger = format == MONO_DEBUG_FORMAT_DEBUGGER;
54 if (in_the_mono_debugger)
55 mono_debugger_initialize ();
57 mono_debugger_lock ();
59 mono_debug_handles = g_hash_table_new_full
60 (NULL, NULL, NULL, (GDestroyNotify) mono_debug_close_image);
62 mono_debugger_class_init_func = mono_debug_add_type;
63 mono_install_assembly_load_hook (mono_debug_add_assembly, NULL);
65 mono_debug_open_image (mono_defaults.corlib);
66 for (ass = mono_defaults.corlib->references; ass && *ass; ass++)
67 mono_debug_open_image ((*ass)->image);
71 * Initialize debugging support - part 2.
73 * This method must be called after loading the application's main assembly.
76 mono_debug_init_2 (MonoAssembly *assembly)
78 mono_debug_open_image (assembly->image);
80 mono_debug_add_type (mono_defaults.object_class);
81 mono_debug_add_type (mono_defaults.object_class);
82 mono_debug_add_type (mono_defaults.byte_class);
83 mono_debug_add_type (mono_defaults.void_class);
84 mono_debug_add_type (mono_defaults.boolean_class);
85 mono_debug_add_type (mono_defaults.sbyte_class);
86 mono_debug_add_type (mono_defaults.int16_class);
87 mono_debug_add_type (mono_defaults.uint16_class);
88 mono_debug_add_type (mono_defaults.int32_class);
89 mono_debug_add_type (mono_defaults.uint32_class);
90 mono_debug_add_type (mono_defaults.int_class);
91 mono_debug_add_type (mono_defaults.uint_class);
92 mono_debug_add_type (mono_defaults.int64_class);
93 mono_debug_add_type (mono_defaults.uint64_class);
94 mono_debug_add_type (mono_defaults.single_class);
95 mono_debug_add_type (mono_defaults.double_class);
96 mono_debug_add_type (mono_defaults.char_class);
97 mono_debug_add_type (mono_defaults.string_class);
98 mono_debug_add_type (mono_defaults.enum_class);
99 mono_debug_add_type (mono_defaults.array_class);
100 mono_debug_add_type (mono_defaults.multicastdelegate_class);
101 mono_debug_add_type (mono_defaults.asyncresult_class);
102 mono_debug_add_type (mono_defaults.waithandle_class);
103 mono_debug_add_type (mono_defaults.typehandle_class);
104 mono_debug_add_type (mono_defaults.fieldhandle_class);
105 mono_debug_add_type (mono_defaults.methodhandle_class);
106 mono_debug_add_type (mono_defaults.monotype_class);
107 mono_debug_add_type (mono_defaults.exception_class);
108 mono_debug_add_type (mono_defaults.threadabortexception_class);
109 mono_debug_add_type (mono_defaults.thread_class);
110 mono_debug_add_type (mono_defaults.transparent_proxy_class);
111 mono_debug_add_type (mono_defaults.real_proxy_class);
112 mono_debug_add_type (mono_defaults.mono_method_message_class);
113 mono_debug_add_type (mono_defaults.appdomain_class);
114 mono_debug_add_type (mono_defaults.field_info_class);
115 mono_debug_add_type (mono_defaults.stringbuilder_class);
116 mono_debug_add_type (mono_defaults.math_class);
117 mono_debug_add_type (mono_defaults.stack_frame_class);
118 mono_debug_add_type (mono_defaults.stack_trace_class);
119 mono_debug_add_type (mono_defaults.marshal_class);
120 mono_debug_add_type (mono_defaults.iserializeable_class);
121 mono_debug_add_type (mono_defaults.serializationinfo_class);
122 mono_debug_add_type (mono_defaults.streamingcontext_class);
124 mono_debugger_unlock ();
128 mono_debug_cleanup (void)
130 mono_debugger_cleanup ();
132 if (mono_debug_handles)
133 g_hash_table_destroy (mono_debug_handles);
134 mono_debug_handles = NULL;
137 static MonoDebugHandle *
138 _mono_debug_get_image (MonoImage *image)
140 return g_hash_table_lookup (mono_debug_handles, image);
143 static MonoDebugHandle *
144 mono_debug_open_image (MonoImage *image)
146 MonoDebugHandle *handle;
148 handle = _mono_debug_get_image (image);
152 handle = g_new0 (MonoDebugHandle, 1);
153 handle->image = image;
154 handle->image->ref_count++;
155 handle->image_file = g_strdup (image->name);
156 handle->_priv = g_new0 (MonoDebugHandlePriv, 1);
158 g_hash_table_insert (mono_debug_handles, image, handle);
160 if (image->assembly->dynamic)
163 handle->symfile = mono_debug_open_mono_symbol_file (handle, in_the_mono_debugger);
164 if (in_the_mono_debugger)
165 handle->_priv->debugger_info = mono_debugger_add_symbol_file (handle);
171 mono_debug_close_image (MonoDebugHandle *handle)
174 mono_debug_close_mono_symbol_file (handle->symfile);
175 handle->image->ref_count--;
176 g_free (handle->_priv);
181 mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data)
183 mono_debugger_lock ();
184 mono_debug_open_image (assembly->image);
185 mono_debugger_unlock ();
189 * This is called via the `mono_debugger_class_init_func' from mono_class_init() each time
190 * a new class is initialized.
193 mono_debug_add_type (MonoClass *klass)
195 MonoDebugHandle *handle;
197 handle = _mono_debug_get_image (klass->image);
200 if (handle->_priv->debugger_info)
201 mono_debugger_add_type (handle->_priv->debugger_info, klass);
204 struct LookupMethodData
206 MonoDebugMethodInfo *minfo;
211 lookup_method_func (gpointer key, gpointer value, gpointer user_data)
213 MonoDebugHandle *handle = (MonoDebugHandle *) value;
214 struct LookupMethodData *data = (struct LookupMethodData *) user_data;
220 data->minfo = mono_debug_find_method (handle->symfile, data->method);
223 static MonoDebugMethodInfo *
224 _mono_debug_lookup_method (MonoMethod *method)
226 struct LookupMethodData data;
229 data.method = method;
231 if (!mono_debug_handles)
234 g_hash_table_foreach (mono_debug_handles, lookup_method_func, &data);
239 * This is called by the JIT to tell the debugging code about a newly compiled
243 mono_debug_add_wrapper (MonoMethod *method, MonoMethod *wrapper_method, MonoDomain *domain)
245 MonoClass *klass = method->klass;
246 MonoDebugHandle *handle;
247 MonoDebugMethodInfo *minfo;
248 MonoDebugMethodJitInfo *jit;
249 MonoDebugDomainData *domain_data;
251 if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
254 mono_class_init (klass);
256 handle = _mono_debug_get_image (klass->image);
259 minfo = _mono_debug_lookup_method (method);
263 domain_data = mono_debug_get_domain_data (handle, domain);
264 g_assert (!domain_data->jit [minfo->index]);
266 jit = g_hash_table_lookup (domain_data->_priv->wrapper_info, wrapper_method);
269 mono_debugger_lock ();
271 domain_data->jit [minfo->index] = jit;
272 jit->wrapper_addr = method->addr;
274 if (handle->_priv->debugger_info && (domain == mono_root_domain))
275 mono_debugger_add_method (handle->_priv->debugger_info, minfo, jit);
277 mono_debugger_unlock ();
281 * This is called by the JIT to tell the debugging code about a newly
285 mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDomain *domain)
287 MonoClass *klass = method->klass;
288 MonoDebugDomainData *domain_data;
289 MonoDebugHandle *handle;
290 MonoDebugMethodInfo *minfo;
292 mono_class_init (klass);
294 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
295 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
296 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
297 (method->flags & METHOD_ATTRIBUTE_ABSTRACT))
300 handle = _mono_debug_get_image (klass->image);
303 minfo = _mono_debug_lookup_method (method);
307 mono_debugger_lock ();
309 domain_data = mono_debug_get_domain_data (handle, domain);
310 g_assert (!domain_data->jit [minfo->index]);
312 if (method->wrapper_type != MONO_WRAPPER_NONE) {
313 g_hash_table_insert (domain_data->_priv->wrapper_info, method, jit);
314 mono_debugger_unlock ();
318 domain_data->jit [minfo->index] = jit;
320 if (handle->_priv->debugger_info && (domain == mono_root_domain))
321 mono_debugger_add_method (handle->_priv->debugger_info, minfo, jit);
323 mono_debugger_unlock ();
327 il_offset_from_address (MonoDebugMethodJitInfo *jit, guint32 address)
331 if (!jit || !jit->line_numbers)
334 for (i = jit->line_numbers->len - 1; i >= 0; i--) {
335 MonoDebugLineNumberEntry lne = g_array_index (
336 jit->line_numbers, MonoDebugLineNumberEntry, i);
338 if (lne.address <= address)
346 * Used by the exception code to get a source location from a machine address.
348 * Returns a textual representation of the specified address which is suitable to be displayed to
349 * the user (for instance "/home/martin/monocvs/debugger/test/Y.cs:8").
351 * If the optional @line_number argument is not NULL, the line number is stored there and just the
352 * source file is returned (ie. it'd return "/home/martin/monocvs/debugger/test/Y.cs" and store the
353 * line number 8 in the variable pointed to by @line_number).
356 mono_debug_source_location_from_address (MonoMethod *method, guint32 address, guint32 *line_number,
359 MonoDebugMethodInfo *minfo = _mono_debug_lookup_method (method);
360 MonoDebugDomainData *domain_data;
365 domain_data = mono_debug_get_domain_data (minfo->handle, domain);
366 if (!domain_data->jit [minfo->index])
370 gint32 offset = il_offset_from_address (domain_data->jit [minfo->index], address);
375 return mono_debug_find_source_location (minfo->handle->symfile, method, offset, line_number);
382 * Used by the exception code to get a source location from an IL offset.
384 * Returns a textual representation of the specified address which is suitable to be displayed to
385 * the user (for instance "/home/martin/monocvs/debugger/test/Y.cs:8").
387 * If the optional @line_number argument is not NULL, the line number is stored there and just the
388 * source file is returned (ie. it'd return "/home/martin/monocvs/debugger/test/Y.cs" and store the
389 * line number 8 in the variable pointed to by @line_number).
392 mono_debug_source_location_from_il_offset (MonoMethod *method, guint32 offset, guint32 *line_number)
394 MonoDebugMethodInfo *minfo = _mono_debug_lookup_method (method);
396 if (!minfo || !minfo->handle)
399 return mono_debug_find_source_location (minfo->handle->symfile, method, offset, line_number);
403 * Returns the IL offset corresponding to machine address @address which is an offset
404 * relative to the beginning of the method @method.
407 mono_debug_il_offset_from_address (MonoMethod *method, gint32 address, MonoDomain *domain)
409 MonoDebugMethodInfo *minfo;
410 MonoDebugDomainData *domain_data;
415 minfo = _mono_debug_lookup_method (method);
416 if (!minfo || !minfo->il_offsets)
419 domain_data = mono_debug_get_domain_data (minfo->handle, domain);
421 return il_offset_from_address (domain_data->jit [minfo->index], address);
425 * Returns the machine address corresponding to IL offset @il_offset.
426 * The returned value is an offset relative to the beginning of the method @method.
429 mono_debug_address_from_il_offset (MonoMethod *method, gint32 il_offset, MonoDomain *domain)
431 MonoDebugMethodInfo *minfo;
432 MonoDebugDomainData *domain_data;
437 minfo = _mono_debug_lookup_method (method);
438 if (!minfo || !minfo->il_offsets)
441 domain_data = mono_debug_get_domain_data (minfo->handle, domain);
443 return _mono_debug_address_from_il_offset (domain_data->jit [minfo->index], il_offset);
446 MonoDebugDomainData *
447 mono_debug_get_domain_data (MonoDebugHandle *handle, MonoDomain *domain)
449 MonoDebugDomainData *data;
451 for (data = handle->_priv->domain_table; data; data = data->_priv->next)
452 if (data->domain_id == domain->domain_id)
455 data = g_new0 (MonoDebugDomainData, 1);
456 data->domain_id = domain->domain_id;
457 data->jit = g_new0 (MonoDebugMethodJitInfo *, handle->symfile->offset_table->method_count + 1);
459 data->_priv = g_new0 (MonoDebugDomainDataPriv, 1);
460 data->_priv->next = handle->_priv->domain_table;
461 data->_priv->wrapper_info = g_hash_table_new (g_direct_hash, g_direct_equal);
462 handle->_priv->domain_table = data;