[[!meta copyright="Copyright © 2007, 2008, 2009 Free Software Foundation,
Inc."]]

[[!meta license="""[[!toggle id="license" text="GFDL 1.2+"]][[!toggleable
id="license" text="Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU Free Documentation License, Version 1.2 or
any later version published by the Free Software Foundation; with no Invariant
Sections, no Front-Cover Texts, and no Back-Cover Texts.  A copy of the license
is included in the section entitled
[[GNU Free Documentation License|/fdl]]."]]"""]]

Mach has a built-in kernel debugger.
[Manual](http://www.gnu.org/software/hurd/gnumach-doc/Kernel-Debugger.html).


When you're [[running_a_system_in_QEMU|hurd/running/qemu]] you can directly
[use GDB on the running
kernel](http://www.nongnu.org/qemu/qemu-doc.html#SEC48).


Alternatively you can use an approach like this one: add the following code
snippet to `device/ds_routines.c`'s `ds_device_open` function, right at the top
of the function, and modify the code as needed.

      void D (char *s)
      {
        switch (s[0] - '0')
          {
          case 0:
           printf ("Hello from %s!\n", __FUNCTION__);
           break;
          case 1:
           printf ("%s: Invoking task_collect_scan.\n", __FUNCTION__);
           extern void task_collect_scan (void);
           task_collect_scan ();
           break;
          default:
           printf ("No idea what you want me to do.\n");
           break;
          }
      }
    
      if (name && name[0] == 'D')
        D (name + 1);

Then boot your system and do something like this:

    # devprobe D0
    Hello from D!
    # devprobe D1
    D: Invoking task_collect_scan.
    # devprobe D2
    No idea what you want me to do.

This is especially useful if you need to manually trigger some stuff inside the
running kernel, as with the *D1* example.


If you're doing real low level debugging, you might want to put variations of
the following snipped into the code, this code will write a `#` character at
line `[LINE]`, column `[COLUMN]` on the screen:

    *((char *) 0xb8000 + 2 * ([LINE] * 80 + [COLUMN])) = '#';
    halt_cpu ();

The call of `halt_cpu` will -- as the name suggests -- halt the system
afterwards.  This might be what you want or it might not, but it is needed at
some place when running the kernel inside QEMU, as QEMU somehow decides not to
update its display buffer anymore under certain conditions.