How To Debug
Here are some tips to debug GRUB.
General Problems
If a problem is generic (i.e. not machine-specific), the easiest way is to use grub-emu. Note that you can attach gdb to it, and apply strace or whatever else.
Memory Problems
If grub-emu is not usable in your problem, and it is related to the memory management, configure GRUB with --enable-mm-debug. You can trace all memory function calls on the screen. Since the output can be quite long, if you enable this feature, you are likely to lose earlier messages from the screen. So it is necessary to pinpoint where is suspicious. You can enable and disable this feature by embedding this kind of code:
grub_mm_debug = 1; suspicious_function (); grub_mm_debug = 0;
Note that grub_mm_debug is declared in grub/mm.h only when --enable-mm-debug is specified. If necessary, call grub_abort to stop the execution.
Other problems
Generally speaking, it is the most powerful to print log messages. Also, you should make the testing as quick as possible to make your work efficient. For example, using an emulator, such as qemu, is the fastest way for a boot loader. Or, netbooting is also very efficient, as you do not have to exchange disks. In addition, do not hesitate to write shell scripts or small code only for testing.
If you think the debug messages you put can help solving future problems, you can use grub_dprintf.
grub_dprintf("trigger", "format_string", ...);
Where trigger is the name searched for in the "debug" environment variable, forma_string is a usual format string as in grub_printf, with usual optionnal arguments. You can then enable this log message by setting the "debug" environment variable to the trigger value (along with other trigger values, separated by any of space " ", tab "\t", colon ",", semicolon ";", pipe "|", ampersand "&", line feed "\n", and cariage return "\r"). The special value "all" triggers all debug messages. Subwords are not matched : foo_bar will not be displayed if debug=foo.
Debugging with GDB
If the above is not enough to trace your problem, you might like to connect GDB to your GRUB. You can do so either using a machine emulator like Qemu or Bochs, or debug GRUB running on a physical machine via serial line. See DebuggingWithGDB for details.
Obtaining a debug trace
To obtain a debug trace that you can save into a file (e.g. for sending it to the developers), you can do the following:
Attach a serial cable, and run a terminal client (e.g. minicom or cu) in the other end that logs everything. Then, from the local console, run:
serial terminal serial
(if it crashes when you issue one of the two first commands, try preloading serial.mod and terminal.mod (--modules parameter to grub-install))
From the other end (at 9600 8N1):
set debug=all
Followed by anything you need to exhibit the bad behaviour.
Alternatively, you can try reproducing the problem inside grub-emu (enabled with --enable-grub-emu), which will save you from setting up a serial link.