How to use kgdb: Difference between revisions
Line 13: | Line 13: | ||
Commands to be run on the <span style="background:#FFFFC0">Ubuntu host</span> have a yellow background. Commands to be run on the <span style="background:#C0FFFF">ARM target</span> have an aqua background. | Commands to be run on the <span style="background:#FFFFC0">Ubuntu host</span> have a yellow background. Commands to be run on the <span style="background:#C0FFFF">ARM target</span> have an aqua background. | ||
=== Configure kernel for kgdb support === | === Configure kernel for kgdb support === | ||
* <span style="background:#FFFFC0">Set CONFIG_DEBUG_INFO=y</span> | Add to kernel command line in order to stop kernel boot and attach kgdb<br> | ||
<pre>kgdboc=ttyS0,115200 kgdbwait | |||
</pre> | |||
<br> | |||
*<span style="background:#FFFFC0">Set CONFIG_DEBUG_INFO=y</span> | |||
CONFIG_DEBUG_INFO: | CONFIG_DEBUG_INFO: | ||
If you say Y here the resulting kernel image will include | |||
debugging info resulting in a larger kernel image. | |||
This adds debug symbols to the kernel and modules (gcc -g), and | |||
is needed if you intend to use kernel crashdump or binary object | |||
tools like crash, kgdb, LKCD, gdb, etc on the kernel. | |||
Say Y here only if you plan to debug the kernel. | |||
If unsure, say N. | |||
Symbol: DEBUG_INFO [=y] | |||
Prompt: Compile the kernel with debug info | |||
Defined at lib/Kconfig.debug:575 | |||
Depends on: DEBUG_KERNEL | |||
Location: | |||
-> Kernel configuration | |||
-> Kernel hacking | |||
* <span style="background:#FFFFC0">Set CONFIG_KGDB=y</span> | *<span style="background:#FFFFC0">Set CONFIG_KGDB=y</span> | ||
menuconfig KGDB | menuconfig KGDB | ||
bool "KGDB: kernel debugging with remote gdb" | |||
depends on HAVE_ARCH_KGDB | |||
depends on DEBUG_KERNEL && EXPERIMENTAL | |||
help | |||
If you say Y here, it will be possible to remotely debug the | |||
kernel using gdb. | |||
* <span style="background:#FFFFC0">Set CONFIG_KGDB_CONSOLE=y</span> | *<span style="background:#FFFFC0">Set CONFIG_KGDB_CONSOLE=y</span> | ||
config KGDB_SERIAL_CONSOLE | config KGDB_SERIAL_CONSOLE | ||
tristate "KGDB: use kgdb over the serial console" | |||
select CONSOLE_POLL | |||
select MAGIC_SYSRQ | |||
default y | |||
help | |||
Share a serial console with kgdb. Sysrq-g must be used | |||
to break in initially. | |||
=== Setup runtime for kgdb usage === | === Setup runtime for kgdb usage === |
Revision as of 19:47, 25 February 2014
I have found kgdb a great way to learn about various parts of the kernel, such as how driver probing works. That said, others have strong opinions:
Do _not_ use kgdb - which is the modus operandi of every sane kernel developer on the planet.
quote from Thomas Gleixner (kernel contributions include High Resolution Timers, Realtime-Linux with Ingo Molnar, and NAND flash driver), who clearly thinks kgdb isn't needed.
Overview of key steps
Commands to be run on the Ubuntu host have a yellow background. Commands to be run on the ARM target have an aqua background.
Configure kernel for kgdb support
Add to kernel command line in order to stop kernel boot and attach kgdb
kgdboc=ttyS0,115200 kgdbwait
- Set CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO: If you say Y here the resulting kernel image will include debugging info resulting in a larger kernel image. This adds debug symbols to the kernel and modules (gcc -g), and is needed if you intend to use kernel crashdump or binary object tools like crash, kgdb, LKCD, gdb, etc on the kernel. Say Y here only if you plan to debug the kernel. If unsure, say N. Symbol: DEBUG_INFO [=y] Prompt: Compile the kernel with debug info Defined at lib/Kconfig.debug:575 Depends on: DEBUG_KERNEL Location: -> Kernel configuration -> Kernel hacking
- Set CONFIG_KGDB=y
menuconfig KGDB bool "KGDB: kernel debugging with remote gdb" depends on HAVE_ARCH_KGDB depends on DEBUG_KERNEL && EXPERIMENTAL help If you say Y here, it will be possible to remotely debug the kernel using gdb.
- Set CONFIG_KGDB_CONSOLE=y
config KGDB_SERIAL_CONSOLE tristate "KGDB: use kgdb over the serial console" select CONSOLE_POLL select MAGIC_SYSRQ default y help Share a serial console with kgdb. Sysrq-g must be used to break in initially.
Setup runtime for kgdb usage
- Boot into Linux
- Enable inetd so you can telnet into hardware
- On the target, switch console tty device for use with kgdb
echo ttyS0 > /sys/module/kgdboc/parameters/kgdboc echo g > /proc/sysrq-trigger
The SysRq command is also useful in order to stop kernel execution, sometimes it is normal to use at gdb the continue commands and the kernel will continue running without finding a break point, in order to stop kernel execution when desired send the SysRq command and kernel will stop at the gdb console:
echo g > /proc/sysrq-trigger
- On the host, exit terminal emulator (picocom) and run gdb
cd $DEVDIR/kernel/linux-* arm-linux-gnueabi-gdb -tui # or maybe arm-none-linux-gnueabi-gdb -tui file vmlinux set remotebaud 115200 target remote /dev/ttyUSB3 break uart_register_driver continue
In telnet window, cause the breakpoint to be tripped
Loadable modules and kgdb
Load the module and learn the load address.
modprobe sc16is7 lsmod
You should get output something like
sc16is7 9793 0 - Live 0xbf000000
where 0xbf000000 is the module starting virtual address.
Tell the gdb about the module
add-symbol-file drivers/serial/sc16is7.o 0xbf000000
Hints
- If you want to interrupt a running kernel and you get back to the gdb prompt
echo g > /proc/sysrq-trigger
- Don't try to debug parts of the kernel that deal with scheduling/execution control. Don't even try to step over them with the next function. Instead, set a breakpoint after the function call to get gdb back in control. Some of the scheduling/execution control functions to watch out for include:
queue_work() spin_lock() spin_unlock()
As you are stepping though code and approach one of these functions, such as:
│199 int tty_buffer_request_room(struct tty_struct *tty, size_t size) │200 { │201 struct tty_buffer *b, *n; │202 int left; │203 unsigned long flags; │204 >│205 spin_lock_irqsave(&tty->buf.lock, flags); │206 │207 /* OPTIMISATION: We could keep a per tty "zero" sized buffer │208 remove this conditional if its worth it. This would be │209 to the callers */ │210 if ((b = tty->buf.tail) != NULL) (gdb) s tty_buffer_request_room (tty=0xc21b1000, size=1) at drivers/char/tty_buffer.c:200 (gdb)
You can skip the function by setting a temporary breakpoing on a line of code after the function call, such as:
(gdb) tbreak 210 Breakpoint 2 at 0xc018e548: file drivers/char/tty_buffer.c, line 210. (gdb) continue Continuing. tty_buffer_request_room (tty=0xc21b1000, size=1) at drivers/char/tty_buffer.c:210 (gdb)
Then you can continue using gdb normally.