There are many reason why would you wish to debug GRUB 2 running on real hardware. You might want do debug routines that use hardware which is emulated neither by QEMU no Bochs, say driver for non-ne2000 network adapter. In cases like this, you need to use remote GDB connected to a testbed machine with GRUB 2 that has GDB stub over a serial line. I also recommend you to connect both machines with ethernet, so that you can transfer GRUB 2 kernel from the development machine to the testbed machine easily -- over TFTP.
Buy, borrow, steal or make yourself DTE-DTE serial cable (frequently referred to as null-modem). If you decide to make it, search Google for a wire map or use one below this paragraph. Connect RS-232 interfaces of both development machine and testbed one together.
If you want to use TFTP to transfer the GRUB 2 kernel, you need to enable TFTP server on the development machine and compile GRUB Legacy with support for ethernet adapter of your testbed machine. If your operating system uses BSD-style network daemons add (or uncomment) something like follwing to /etc/inetd.conf:
tftp dgram udp wait root /usr/libexec/tftpd tftpd /tftprootReload the inetd configuration afterwards:
# pkill -HUP inetd
The debugging stub is not a part of the GNU GRUB distribution, so you have to patch the sources with the grub2-gdb-stub.diff patch. Please note that as this patch extends the uncompressable part of the kernel, you have to use grub-mkimage built from the patched source tree to generate core images. Be sure to include the gdb module when building the core image.
grub2$ patch < ~/grub2-gdb-stub.diff grub2$ ./configure && gmake ... grub2$ grub-mkimage -d. -o /tftproot/core.img gdb
Compile GRUB Legacy with support for your testbed machine's ethernet adapter and install it on the testbed machine. To load GRUB 2 kernel from the development machine use theese commands (with addresses valid in your network):
(grub) ifconfig --address=192.168.1.2 --server=192.168.1.1 ... (grub) root (nd) ... (grub) kernel /tftproot/core.img ... (grub) boot ...
Now, after you started GRUB 2, configure the serial port with serial command. It is probably a good idea to use the highest available baud rate instead of the default 9600 bps. When serial port is configured you can start listening for GDB connection with break command. GDB stub will also be passed control when any CPU exception occurs (division by zero, access beyond available memory range, etc.).
(grub) serial --speed=115200 (grub) break Now connect the remote debugger, please.
Connect GDB.
(gdb) remotebaud 115200 (gdb) target remote /dev/modem ...
Some operations can be really slow. For example load_all_modules with 9 modules loaded take around a minute and a half. Probably GDB's set remotecache on can improve performance in some cases. If you are sure that your GDB session is not performing a lengthy operation, but it really froze, please enable set remotedebug on and send me the output.
It is not a good idea to set breakpoints to either serial port communication code ot the gdb stub code itself. You know why.