* How do I enter a JIT trampoline ?

  Normally, the debugger hides JIT trampolines from the user, even when stepping one single
  instruction.  To force the debugger to debug a JIT trampoline, you need to use the
  `native stepi' command in the command line interface.


* How do I enter an interncall ?

  There are two ways of entering an interncall: if the module the interncall is contained in
  has debugging info and the `step' property is set (use `module <number> !ignore step' in the
  command line interface), the debugger will automatically enter the interncall when stepping
  by source lines.

  Example debugging session:

        [martin@einstein debugger]$ run-mono ./lib/Interpreter.exe ./test/N.exe
        Process @1 stopped at #0: 0x08365f63 in X.Main()+0x7 at N.cs:7.
        #0: 0x08365f63 in X.Main()+0x7 at N.cs:7
        0x08365f63      push   $0x41
           7            bool is_number = Char.IsNumber ('A');
        Mono debugger
        $ show modules
        3 /home/martin/MONO-LINUX/libexec/mono-debugger-jit-wrapper loaded ignore
        5 N loaded symbols step
        7 /home/martin/MONO-LINUX/lib/libmono.so.0 loaded ignore
        9 mscorlib loaded symbols step
        $ module 7 !ignore step
        $ s
        Process @1 stopped at #0: 0x400aa12c in ves_icall_System_Char_IsNumber+0x1c at unicode.c:110.
        0x400aa12c      movzwl 0xfffffff2(%ebp),%eax
        110    GUnicodeType t = g_unichar_type (c);

  You can also "force" the debugger to enter the intercalls by stepping by machine instructions;
  in this case, the debugger will automatically jump over the JIT trampoline and stop at the
  first instruction of the interncall.

  Example debugging session:

        [martin@einstein debugger]$ run-mono ./lib/Interpreter.exe ./test/N.exe
        Process @1 stopped at #0: 0x08366013 in X.Main()+0x7 at N.cs:7.
        #0: 0x08366013 in X.Main()+0x7 at N.cs:7
        0x08366013      push   $0x41
         7            bool is_number = Char.IsNumber ('A');
        Mono debugger
        $ i
        Process @1 stopped at #0: 0x08366018 in X.Main()+0xc at N.cs:7.
        0x08366018      call   System.Char.IsNumber(System.Char)
         7            bool is_number = Char.IsNumber ('A');
        $
        Process @1 stopped at #0: 0x400aa110.
        0x400aa110      push   %ebp


* Why aren't we using gdb as the backend ?

  Unfortunately, using gdb as the backend would have been a lot more work than writing our
  own backend from scratch.  Basically, there were more things in gdb which we could not use
  than things we could use - and there were also serious performance issues.

  It might make sense to write a gdb backend to port the debugger to all architectures -
  however, the debugger's platform/architecture specific code is less than 1500 lines of
  code, so it may also be easier to port this directly.


* The debugger has problems finding `MONO_DEBUGGER__debugger_info'

  You need to have a Debugger.exe.config file containing the full path name of your `mono'
  executable.  Normally, this file is automatically generated.

  The `MONO_DEBUGGER__debugger_info' symbol must be in the `mono' executable itself, not in
  a shared library, it is read by the debugger before loading any shared libraries.


* What are the requirements to get the debugger up and running on GNU/Linux ?

  To get all the cool features of the GUI, you need gtk# and GNOME 2.

  However, the backend and the command-line interface only depends on glib (the C library,
  not glib-sharp.dll) and binutils >= 2.12 (some distros may have an older version of it).


* Can I debug Mono class libraries with it, such as corlib or System.Data ?

  Sure you can do this.  All you need to do is to compile them with debugging support (mcs -g).


* Can it be used to debug code which uses unmanaged code via DllImport or interncalls ?

  The debugger can debug managed and unmanaged applications - and while debugging managed
  applications, you can also enter interncalls and stuff like that (actually, the debugger
  has an option to turn this feature on and off).


* Can I use the debugger to debug GTK# or QT# applications on Mono?

  There is no reason why you shouldn't be able to do this.


* Can the debugger be ported to other platforms, such as, Linux/PPC, FreeBSD/i386, or dare
  I say Windows 2000 ?  If so, what would it take to port the debugger to other platforms?

  We need to distinguish between hardware architectures and operating systems here.

  To port the debugger to another operating system, have a look at backends/server/server.h -
  this is an unmanaged API which you need to implement for that other operating system.  The
  current Linux implementation is in i386-linux-ptrace.c.

  To port the debugger to another hardware architecture, you also need to implement the
  managed IArchitecture interface; the current i386 implementation is in
  arch/ArchitectureI386.cs.  I'm currently using architecture-specific stuff in
  i386-linux-ptrace.c because there's just one architecture; it may be a good idea to split
  this file - all the ptrace() stuff should be the same for Linux/PPC, for instance.

  It shouldn't be that difficult to port the debugger to another hardware architecture or
  another Unix system - but I have no idea whether it'll be possible to port it to any
  flavor of Windows.  In any case, such a port would be a huge task and much more difficult
  than porting it to another Unix system.

  The problem is that to debug unmanaged applications, the debugger is using the bfd and
  libopcodes libraries - which have already been ported to a lot of different Unix systems.


* What features does debugger have?  How does this differ from other debuggers out there?

  Well, it has a lot of features :-)

  However, the coolest feature I added last week are per-thread breakpoints - if you're
  debugging a multi-threaded application, you can tell the debugger that a particular
  breakpoint should only break in a particular thread - and this works without hardware
  breakpoints.

  This'll be very important when debugging system libraries such as System.Data in a
  multi-threaded application because the method you're currently debugging may be called
  from another thread in the meantime.


* I thought that single stepping of source code lines was typically implemented by setting
  a breakpoint on the next instruction.  Why aren't we doing this ?

  The problem is that you don't know where the "next instruction" is without reading and
  analysing the machine code.  Each instruction could be a call or a (conditional) jump - so
  even if your source line is a "basic block" in C# (something which contains no jumps and
  calls), this doesn't need to be the case in the generated machine code.

  The other problem is that setting a breakpoint on the next instruction is about three
  times more expensive that stepping a single machine instruction (read insn, write
  breakpoint, continue, wait, write old insn instead of step, wait) plus the risk that
  another thread may hit the breakpoint in the meantime plus the problem that breakpoints
  don't work everywhere (so you won't be able to step through x86_magic_trampoline(), for
  instance).

* I'm getting an undefined symbol `_sch_istable'.

  Please read the section "binutils and libbfd issues" in README.FreeBSD.

