Kernel debugging may seem a daunting task but it's possible to solve a whole load of deep issues with some very simple tools. In fact, my number one debugging tool is printk().
Believe it or not, printing out the state of the kernel at specific key areas can reveal a whole load of useful information which can then help corner a bug.
Of course, using printk() has it's issues; it adds extra code to the kernel which can possibly move the bug around or make the bug behave differently if there is a timing or race condition.
Occasionally, one needs to be able to dump a whole load of console messages over a serial line to enable one to capture the state of the machine when the PC console is not available. However, printk() still does the trick.
If you want to know more, I've started the Kernel Debugging Tricks wiki page with some of my debug hacks on it. Feel free to contribute if you have any helpful debugging tricks!