[Mono-list] Source lines in backtraces ....
Martin Baulig
martin@gnome.org
21 May 2002 22:07:23 +0200
Hi guys,
after a long day of hacking, there's a cool new toy for you :-)
The JIT engine `mono' now displays source lines and IL offset in
stack traces if you enabled the debugging support.
There are two ways to do this:
1.) Use the "dwarf" / "stabs" debugging format.
This works for every assembly - no matter whether it has been
compiled with mcs or csc.
Just start mono like this:
mono --debug dwarf <yourapp.exe>
or
mono --debug stabs <yourapp.exe>
Here's a real-life example:
=====
mono --debug dwarf mcs.exe --timestamp -o mcs-mono2.exe -g assign.cs attribute.cs driver.cs cs-parser.cs cs-tokenizer.cs tree.cs location.cs cfold.cs class.cs codegen.cs const.cs constant.cs decl.cs delegate.cs enum.cs ecore.cs expression.cs genericparser.cs interface.cs literal.cs modifiers.cs namespace.cs parameter.cs report.cs rootcontext.cs statement.cs support.cs typemanager.cs
Recreating mcs.il from mcs.exe.
Recreating corlib.il from /home/martin/MONO-LINUX/lib/corlib.dll.
[04:162] Loading references
[00:040] References loaded
Recreating Mono.CSharp.Debugger.il from /home/martin/MONO-LINUX/lib/Mono.CSharp.Debugger.dll.
[00:515] Initializing Core Types
[00:003] Core Types done
[00:000] Resolving tree
[00:064] Populate tree
[01:268] Emitting code
[14:063] done
[00:000] Closing types
[00:266] Saved output
(process:31654): ** WARNING **: unhandled exception System.NullReferenceException: "A null value was found where an object
instance was required"
in (unmanaged) System.Reflection.MonoCMethod:InternalInvoke ()
in [0x00003] (at corlib.il:143483) System.Reflection.MonoCMethod:Invoke (System.Reflection.BindingFlags,System.Reflection.Binder,object[],System.Globalization.CultureInfo)
in [0x00035] (at Mono.CSharp.Debugger.il:5458) .DieSubProgram:get_abbrev_id (DieCompileUnit,Mono.CSharp.Debugger.ISourceMethod)
in [0x00004] (at Mono.CSharp.Debugger.il:5492) .DieSubProgram:.ctor (DieCompileUnit,Mono.CSharp.Debugger.ISourceMethod)
in [0x00007] (at Mono.CSharp.Debugger.il:9305) Mono.CSharp.Debugger.MonoSymbolWriter:WriteMethod (DieCompileUnit,Mono.CSharp.Debugger.ISourceMethod)
in [0x00031] (at Mono.CSharp.Debugger.il:9398) Mono.CSharp.Debugger.MonoSymbolWriter:WriteSource (Mono.CSharp.Debugger.DwarfFileWriter,Mono.CSharp.Debugger.ISourceFile)
in [0x00032] (at Mono.CSharp.Debugger.il:9557) Mono.CSharp.Debugger.MonoSymbolWriter:CreateDwarfFile (string)
in [0x00031] (at Mono.CSharp.Debugger.il:8792) Mono.CSharp.Debugger.MonoSymbolWriter:Close ()
in [0x00011] (at mcs.il:44681) Mono.CSharp.CodeGen:SaveSymbols ()
in [0x00a84] (at mcs.il:10487) Mono.CSharp.Driver:MainDriver (string[])
in [0x00011] (at mcs.il:9278) Mono.CSharp.Driver:Main (string[])
======
The *.il files are automatically created for you.
2.) If you compiled your assembly with mcs, you can use the "dwarf2-plus" format to get
the lines in your C# source code.
You need to compile your app with the -g option like this:
mcs -g exception.cs
Then start the JIT like this:
mono --debug dwarf-plus <yourapp.exe>
Here's a real-life example:
=====
[martin@einstein work]$ mcs -g exception.cs
MonoDwarfFileWriter [00:029] Emitting compile units
MonoDwarfFileWriter [00:083] Done
MonoDwarfFileWriter [00:036] Done emitting 34 line numbers
MonoDwarfFileWriter [00:012] Done writing abbrev declarations
MonoDwarfFileWriter [00:020] Done writing 82 reloc entries
RESULT: 0
[martin@einstein work]$ mono --debug dwarf-plus exception.exe
Recreating exception.il from exception.exe.
Recreating corlib.il from /home/martin/MONO-LINUX/lib/corlib.dll.
Void DoTest()
EXCEPTION!
System.ArgumentNullException
Argument cannot be nullSystem.ArgumentNullExceptionin [0x0000d] (at corlib.il:6438) System.Array:Sort (System.Array)
in [0x00006] (at exception.cs:12) MyException.Test:DoTest ()
in (unmanaged) System.Reflection.MonoMethod:InternalInvoke ()
in [0x00004] (at corlib.il:143099) System.Reflection.MonoMethod:Invoke (object,System.Reflection.BindingFlags,System.Reflection.Binder,object[],System.Globalization.CultureInfo)
in [0x00032] (at exception.cs:33) MyException.MyException:Main (string[])
in [0x0000d] (at corlib.il:6438) System.Array:Sort (System.Array)
in [0x00006] (at exception.cs:12) MyException.Test:DoTest ()
in (unmanaged) System.Reflection.MonoMethod:InternalInvoke ()
in [0x00004] (at corlib.il:143099) System.Reflection.MonoMethod:Invoke (object,System.Reflection.BindingFlags,System.Reflection.Binder,object[],System.Globalization.CultureInfo)
in [0x00032] (at exception.cs:33) MyException.MyException:Main (string[])
(process:32129): ** WARNING **: unhandled exception System.ArgumentNullException: "Argument cannot be null"
in [0x0000d] (at corlib.il:6438) System.Array:Sort (System.Array)
in [0x00006] (at exception.cs:12) MyException.Test:DoTest ()
in [0x00068] (at exception.cs:40) MyException.MyException:Main (string[])
RESULT: -1
====
The C# source code is here:
====
using System;
using System.Reflection;
namespace MyException
{
public class Test
{
public void DoTest ()
{
try {
Array.Sort (null);
} catch (ArgumentOutOfRangeException) {
Console.WriteLine ("CAUGHT!");
}
}
}
public class MyException
{
public static void Main (string[] args)
{
Type type = typeof (Test);
Type[] argtypes = {};
MethodInfo method = type.GetMethod ("DoTest", argtypes);
Console.WriteLine (method);
Test test = new Test ();
try {
Object retval = method.Invoke (test, null);
} catch (Exception e) {
Console.WriteLine ("EXCEPTION!");
Console.WriteLine (e);
Console.WriteLine (e.StackTrace);
}
test.DoTest ();
}
}
}
====
Btw. in the stack traces, addresses in [ ] are IL offsets and addresses in < > are
machine addresses.
--
Martin Baulig
martin@gnome.org