[Mono-list] JIT patch for stabs debugging

Martin Baulig martin@gnome.org
10 Mar 2002 02:39:45 +0100


--=-=-=

Hi,

this afternoon I was finally tired of using Console.WriteLine (...)
for debugging and looked at `mono --stabs'.

Here's a patch which makes this finally work.

The patch does two things:

1.) Puts a NOP instruction at the start of every method.

    If you use `mono --debug Something', this buts a breakpoint
    instruction (INT 3) at the start of "Something" - which means
    that the address of Something's first instruction changes, but
    this address is already hard-coded into the stabs file.

    So without the NOP instructions you need to recreate your stabs
    symbol files each time you want to run mono with different --debug
    arguments.

2.) Uses correct line numbers in the stabs file.

    In mono_debug_add_method(), `t->cli_add' is a bytecode offset, but
    not a line number in the .il file.

    For instance, if t->cli_addr == 0xc, the stabs file must contain
    the line number of the method's IL_000c line in the .il file.

=====
2002-03-10  Martin Baulig  <martin@gnome.org>

	* emit-x86.c (arch_compile_method): When emitting stabs debugging
	output, put a nop instruction at the start of all functions so that
	the adresses won't change when using --debug.

	* debug.c (mono_debug_add_method): `tree->cli_addr' is an offset into
	the bytecode area, stabs needs a line number in the .il file. Use the
	new info->moffsets to get the line number.
	(AssemblyDebugInfo): Added `total_lines' and `moffsets' fields.
	`moffsets' is an array of `total_lines' fields (total number of lines
	in the .il file); for each line in the .il field, this array contains
	the bytecode offset if it's an "IL_xxxx" line, -1 if it's the last line
	of a method and 0 otherwise.
	(debug_load_method_lines): Read the whole .il file and initialize the
	info->moffsets field.

====


--=-=-=
Content-Disposition: attachment; filename=jit-debug-patch.txt

Index: ChangeLog
===================================================================
RCS file: /cvs/public/mono/mono/jit/ChangeLog,v
retrieving revision 1.121
diff -u -u -r1.121 ChangeLog
--- ChangeLog	2002/03/08 06:08:46	1.121
+++ ChangeLog	2002/03/09 21:48:12
@@ -1,3 +1,25 @@
+2002-03-10  Martin Baulig  <martin@gnome.org>
+
+	* emit-x86.c (arch_compile_method): When emitting stabs debugging
+	output, put a nop instruction at the start of all functions so that
+	the adresses won't change when using --debug.
+
+	* debug.c (mono_debug_add_method): `tree->cli_addr' is an offset into
+	the bytecode area, stabs needs a line number in the .il file. Use the
+	new info->moffsets to get the line number.
+	(AssemblyDebugInfo): Added `total_lines' and `moffsets' fields.
+	`moffsets' is an array of `total_lines' fields (total number of lines
+	in the .il file); for each line in the .il field, this array contains
+	the bytecode offset if it's an "IL_xxxx" line, -1 if it's the last line
+	of a method and 0 otherwise.
+	(debug_load_method_lines): Read the whole .il file and initialize the
+	info->moffsets field.
+
+2002-03-09  Martin Baulig  <martin@gnome.org>
+
+	* x86.brg (DIV_UN): Clear EDX before performing the division and remove
+	the unnecessary CDQ instruction.
+
 2002-03-07  Dietmar Maurer  <dietmar@ximian.com>
 
 	* jit.c (mono_analyze_stack): only load addresses of value types
Index: debug.c
===================================================================
RCS file: /cvs/public/mono/mono/jit/debug.c,v
retrieving revision 1.6
diff -u -u -r1.6 debug.c
--- debug.c	2002/02/19 06:01:21	1.6
+++ debug.c	2002/03/09 21:48:13
@@ -9,7 +9,9 @@
 	FILE *f;
 	char *filename;
 	char *name;
+	int total_lines;
 	int *mlines;
+	int *moffsets;
 	int nmethods;
 	int next_idx;
 } AssemblyDebugInfo;
@@ -106,21 +108,45 @@
 		g_free (name);
 		return;
 	}
+
+	info->total_lines = 100;
+	info->moffsets = g_malloc (info->total_lines * sizeof (int));
+
 	g_free (name);
 	i = 0;
 	while (fgets (buf, sizeof (buf), f)) {
-		i++;
-		if (sscanf (buf, " // method line %d", &mnum) && mnum < info->nmethods) {
-			while (fgets (buf, sizeof (buf), f)) {
-				++i;
-				if (strstr (buf, "}"))
-					break; /* internalcall or runtime method */
-				if (strstr (buf, "IL_0000:"))
-					break;
+		int offset = 0, pos = i;
+
+		++i;
+		if (!sscanf (buf, " // method line %d", &mnum))
+			continue;
+
+		if (mnum >= info->nmethods)
+			break;
+
+		while (fgets (buf, sizeof (buf), f)) {
+			int newoffset;
+
+			++i;
+			if (i + 2 >= info->total_lines) {
+				info->total_lines += 100;
+				info->moffsets = g_realloc (info->moffsets, info->total_lines * sizeof (int));
+				g_assert (info->moffsets);
+			}
+
+			if (strstr (buf, "}"))
+				break;
+
+			if (sscanf (buf, " IL_%x:", &newoffset)) {
+				offset = newoffset;
+				if (!offset)
+					pos = i;
 			}
-			/* g_print ("method %d found at %d\n", mnum, i); */
-			info->mlines [mnum] = i;
+
+			info->moffsets [i] = offset;
 		}
+		/* g_print ("method %d found at %d\n", mnum, pos); */
+		info->mlines [mnum] = pos;
 	}
 	fclose (f);
 }
@@ -178,6 +204,7 @@
 {
 	fclose (debug->f);
 	g_free (debug->mlines);
+	g_free (debug->moffsets);
 	g_free (debug->name);
 	g_free (debug->filename);
 	g_free (debug);
@@ -201,14 +228,16 @@
 mono_debug_add_method (MonoDebugHandle* debug, MonoFlowGraph *cfg)
 {
 	char *name;
-	int line = 0;
-	int i;
+	int line = 0, line_index = 0;
+	int i, print;
 	MonoMethod *method = cfg->method;
 	MonoClass *klass = method->klass;
 	MonoMethodSignature *sig = method->signature;
 	char **names = g_new (char*, sig->param_count);
 	AssemblyDebugInfo* info = mono_debug_open_ass (debug, klass->image);
 
+	print = !strcmp (method->name, "Parse") || !strcmp (method->name, "Main");
+
 	/* FIXME: we should mangle the name better */
 	name = g_strdup_printf ("%s%s%s__%s_%p", klass->name_space, klass->name_space [0]? "_": "",
 			klass->name, method->name, method);
@@ -222,6 +251,7 @@
 	 */
 	for (i = 0; klass->methods && i < klass->method.count; ++i) {
 		if (klass->methods [i] == method) {
+			line_index = klass->method.first + i + 1;
 			line = info->mlines [klass->method.first + i + 1];
 			/*g_print ("method %d found at line %d\n", klass->method.first + i + 1, line);*/
 			break;
@@ -232,7 +262,7 @@
 	 * We need to output all the basic info, if we change filename...
 	 * fprintf (info->f, ".stabs \"%s.il\",100,0,0,0\n", klass->image->assembly_name);
 	 */
-	fprintf (info->f, ".stabs \"%s:F(0,%d)\",36,0,%d,%p\n", name, sig->ret->type, line, cfg->start);
+	fprintf (info->f, ".stabs \"%s:F(0,%d)\",36,0,%d,%p\n", name, sig->ret->type, line, cfg->start+1);
 
 	/* params */
 	mono_method_get_param_names (cfg->method, (const char **)names);
@@ -250,12 +280,23 @@
 			fprintf (info->f, ".stabs \"local_%d:(0,%d)=(0,%d)\",128,0,%d,%d\n", i, info->next_idx++, header->locals [i]->type, line, stack_offset);
 		}
 	}
+
+	fprintf (info->f, ".stabn 68,0,%d,%d\n", line, 0);
+
 	/* start lines of basic blocks */
 	for (i = 0; i < cfg->block_count; ++i) {
 		int j;
+
+		// mono_print_forest (cfg->bblocks [i].forest);
+
 		for (j = 0; j < cfg->bblocks [i].forest->len; ++j) {
 			MBTree *t = (MBTree *) g_ptr_array_index (cfg->bblocks [i].forest, j);
-			fprintf (info->f, ".stabn 68,0,%d,%d\n", line + t->cli_addr, t->addr);
+			int *lines = info->moffsets + line, *k = lines;
+
+			while ((*k != -1) && (*k < t->cli_addr))
+				k++;
+
+			fprintf (info->f, ".stabn 68,0,%d,%d\n", line + (k-lines), t->addr-1);
 		}
 	}
 
Index: emit-x86.c
===================================================================
RCS file: /cvs/public/mono/mono/jit/emit-x86.c,v
retrieving revision 1.61
diff -u -u -r1.61 emit-x86.c
--- emit-x86.c	2002/03/08 06:08:46	1.61
+++ emit-x86.c	2002/03/09 21:48:15
@@ -1058,6 +1058,8 @@
 
 		if (match_debug_method (method))
 			x86_breakpoint (cfg->code);
+		else if (mono_debug_handle)
+			x86_nop (cfg->code);
 
 		if (mono_jit_dump_forest) {
 			int i;
Index: x86.brg
===================================================================
RCS file: /cvs/public/mono/mono/jit/x86.brg,v
retrieving revision 1.92
diff -u -u -r1.92 x86.brg
--- x86.brg	2002/03/08 06:08:46	1.92
+++ x86.brg	2002/03/09 21:48:16
@@ -816,7 +816,7 @@
 	if (tree->left->reg1 != X86_EAX)
 		x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
 
-	x86_cdq (s->code);
+	x86_mov_reg_imm (s->code, X86_EDX, 0);
 	x86_div_reg (s->code, tree->right->reg1, FALSE);
 
 	mono_assert (tree->reg1 == X86_EAX &&

--=-=-=


After applying this patch, single stepping through a function now
actually works :-)

-- 
Martin Baulig
martin@gnome.org


--=-=-=--