diff options
Diffstat (limited to 'web/jit-debug')
-rw-r--r-- | web/jit-debug | 215 |
1 files changed, 56 insertions, 159 deletions
diff --git a/web/jit-debug b/web/jit-debug index 867738101ae..57ec9065263 100644 --- a/web/jit-debug +++ b/web/jit-debug @@ -1,181 +1,78 @@ -* How to debug your C# application with the JIT engine +* Debugging information - To debug a C# application you need to run the JIT in your debugger. + Compile your programs using the `-g' flag in MCS, that will all a special + resource containing debugging information to your executable. - Before you can do anything useful in a debugger, you need a symbol - file which tells your debugger about functions, types, line numbers - and such. Unfortunately, this symbol file needs to be recreated each - time the JIT compiles a new method since it doesn't know anything - about this method (especially not its memory address) before actually - compiling it. + To get stack traces with line number information, you need to run your + program like this: - You have two ways of creating a symbol file: + <b> + mono --debug program.exe + </b> -** Letting the JIT dynamically create the symbol file + Notice that the program will need to be compiled with the -g + flag and that running with --debug will slow down the execution. - This'll give you a symbol file which is suitable for debugging IL byte - code - you won't see your C# source code. +* Debugging with GDB - However, this method has the advantage that it works with every assembly, - no matter whether it has been compiled with Mono's C# compiler (MCS) or - with any other compiler. It's currently the only way to debug - <tt>corlib.dll</tt> or any other library which cannot be compiled with - our compiler yet. + If you use GDB to debug your mono process, you can use the function + print_method_from_ip(void *address) to obtain the name of a method + given an address. - All that you need is a dump of the IL bytecode for each assembly (including - all assemblies this assembly is referencing). This is done by using the - <tt>monodis</tt> utility: + For example: <pre> - monodis /home/export/martin/MONO-LINUX/lib/corlib.dll > corlib.il<br> - monodis /home/export/martin/MONO-LINUX/lib/System.dll > System.il<br> - monodis /home/export/martin/MONO-LINUX/bin/mcs.exe > mcs.il - </pre> +(gdb) where +#0 ves_icall_System_String_GetHashCode (me=0x80795d0) at string-icalls.c:861 +#1 0x0817f490 in ?? () +#2 0x0817f42a in ?? () +#3 0x0817f266 in ?? () +#4 0x0817f1a5 in ?? () +</pre> - Make sure that all the .il files have the same name as their corresponding - assembly and that they're all created in the current directory. + You can now use: - The JIT supports two different debugging file formats: +<pre> +(gdb) p print_method_from_ip (0x0817f490) +IP 0x817f490 at offset 0x28 of method (wrapper managed-to-native) System.String:GetHashCode () (0x817f468 0x817f4a4) +$1 = void +(gdb) p print_method_from_ip (0x0817f42a) +IP 0x817f42a at offset 0x52 of method System.Collections.Hashtable:GetHash (object) (0x817f3d8 0x817f43b) +$2 = void +</pre> - <ul> - * STABS: This is a very simple debugging format, but it may be the only one - which is supported on your system. It is limited to source files of no more - than 65.535 lines and it's type support is also very limited. You should only - use this if your debugger doesn't support DWARF 2. + Mono support libraries use a couple of signals internally that + confuse gdb, you might want to add this to your .gdbinit file: - To generate STABS output, use the <tt>--stabs</tt> command line argument. +<pre> + handle SIGPWR nostop noprint + handle SIGXCPU nostop noprint +</pre> +* Mono Debugger - * DWARF 2: The DWARF 2 debugging format is a very powerful debugging format - which can handle source files of arbitrary size and has a highly sophisticated - type support. It's the recommended format unless you need to use STABS because - your debugger doesn't support DWARF 2. + The Mono debugger is written in C# and can debug both managed + and unmanaged applications, support for multiple-threaded + applications and should be relatively easy to port to new + platforms. - To generate DWARF 2 output, use the <tt>--dwarf</tt> command line argument. - </ul> + Details of the release are available in <a + href="http://lists.ximian.com/archives/public/mono-list/2003-January/011415.html">post</a>. + + The debugger contains both Gtk# and command line interfaces. + The debugging file format used in Dwarf (it's already supported + by our class libraries and the Mono C# compiler; To debug C + applications, you need a recent GCC, or to pass the -gdwarf-2 + flag to gcc). + You can download the releases from <a + href="http://primates.ximian.com/~martin/debugger/">Martin Baulig's + home page.</a> - You need to regenerate the symbol file each time the JIT compiled a new - method and each time you restart the JIT. You cannot reuse your symbol file - if you start the JIT a second file, not even if you're running the same - application with the same input data a second time. - Regenerating the symbol file is done by calling the JIT's - <tt>mono_debug_make_symbols ()</tt> function from within your debugger and - then reloading the symbol files. This function creates a <tt>filename-dwarf.s</tt> - (or <tt>filename-stabs.s</tt>) assembler input file in the current directory and - an object file in <tt>/tmp/filename.o</tt> - you need to tell your debugger to - add this object file as symbol file. - - If you're using the GNU debugger, this is done like this: - - <pre> - call mono_debug_make_symbols () - add-symbol-file /tmp/corlib.o - add-symbol-file /tmp/mcs.o - add-symbol-file /tmp/Mono.CSharp.Debugger.o - </pre> - - You can also write a GDB macro like this: - - <pre> - define reload - call mono_debug_make_symbols () - add-symbol-file /tmp/corlib.o - add-symbol-file /tmp/mcs.o - add-symbol-file /tmp/Mono.CSharp.Debugger.o - end - </pre> - - Then you can just say <tt>reload</tt> to have GDB recreate the symbol file. - - There's also an <a href="jit-debug-sample.html">example debugging session</a> using - the GNU debugger. - -** Using a symbol file which have been created by the Mono C# compiler - - If you compiled your application with Mono's C# compiler (MCS), you can tell it to - create a symbol file which is then processed and rewritten by the JIT engine. - - To do this, you must give MCS the <tt>-g</tt> option: - - <pre> - $ mcs -g Foo.cs - </pre> - - This creates a <tt>Foo-debug.s</tt> assembler input file. - - To use this in the JIT, you must first copy it to the target machine (the machine - where you want to run the JIT to debug your application) and run it through the - assembler to produce an object file <tt>Foo-debug.o</tt>. This object file must be - in the current directory. - - Then start the JIT in your debugger and give it the <tt>--dwarf-plus</tt> command - line argument. - - Each time you call <tt>mono_debug_make_symbols ()</tt> from withing your debugger, - the JIT will read this <tt>Foo-debug.o</tt>, fix some machine dependent things like - memory addresses etc. in it and write it back to disk. - - If you're using the GNU debugger, you'll want to use a macro like this: - - <pre> - define relocate - call mono_debug_make_symbols () - add-symbol-file /tmp/corlib.o - add-symbol-file mcs-debug.o - add-symbol-file Mono.CSharp.Debugger-debug.o - end - </pre> - - If there is no <tt>assembly-debug.o</tt> file, but an <tt>assembly.il</tt> one, the - JIT will fall back to normal DWARF 2 (in the example above, <tt>corlib.dll</tt> was - compiled with Microsoft's compiler and the JIT is thus using DWARF to debug it). - - This debugging method only works if you compiled your assembly with MCS, but it'll - allow you to actually debug your C# source code :-) - - Here's an <a href="jit-debug-sample2.html">example debugging session</a> using - the GNU debugger. - -** Breakpoints and single stepping - - The JIT has a <tt>--debug</tt> command line argument to insert a breakpoint at the - beginning of this method. It takes a <tt>Namespace.Class:Method</tt> argument which - is the method. This argument can be given multiple times. - - However, once your application is stopped in GDB you may want to insert a breakpoint - the next time the JIT compiles a method. There's a global variable - <tt>mono_debug_insert_breakpoint</tt> which you can modify in your debugger. - - If this variable is set to a non-zero value, the JIT's <tt>arch_compile_method</tt> - will insert a breakpoint the next time it is called, ie. at the top of the next - method it compiles. If this value has a positive value, it acts as a counter and is - decremented after inserting the breakpoint - setting it to a negative value will let - the JIT insert the breakpoint each time it compiles a new method. - - There's also global variable <tt>mono_debug_last_breakpoint_address</tt> which always - contains the address of the last inserted breakpoint. You may manually override this - address with a <tt>nop</tt> instruction to delete the breakpoint. - - For instance, I have a GDB macro called <tt>enter</tt> which I use to enter a method - rather than stepping over it: - - <pre> - define enter - set mono_debug_insert_breakpoint = 1 - continue - set *mono_debug_last_breakpoint_address = 0x90 - relocate - frame - </pre> - - Btw. speaking of single stepping - you should use your debuggers <tt>next</tt> command, - not its <tt>step</tt> command for single stepping unless you compiled the JIT without - debugging support. The reason for this is that the JIT creates machine code which contains - calls to JIT methods such as <tt>mono_object_new_wrapper</tt> at places where you don't - expect them - so unless the JIT is compiled at least without line numbers, your debugger - will enter such methods if you use <tt>step</tt> rather than <tt>next</tt>. + + + |