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