Debugging with gdb can be augmented greatly via the user of gdb scripts. The GDB manual covers all of this in depth, so this document will contain a bunch of useful snippets.
To load a script at runtime, you can name it
.gdbinit and place it in the directory you execute gdb. Another way is to use the
-x option and specify the script to load automatically.
Note that some of these may make sense only when running with kgdb.
define info-uart # only show read-destructive registers if user requests them ... set $UART_DESTROY = ($argc > 1) set $UART_BASE = $arg0 set $UART_RBR = $UART_BASE + 0x0000 set $UART_DLL = $UART_BASE + 0x0000 set $UART_IER = $UART_BASE + 0x0004 set $UART_DLH = $UART_BASE + 0x0004 set $UART_IIR = $UART_BASE + 0x0008 set $UART_LCR = $UART_BASE + 0x000C set $UART_MCR = $UART_BASE + 0x0010 set $UART_LSR = $UART_BASE + 0x0014 set $UART_SCR = $UART_BASE + 0x001C set $UART_GCTL = $UART_BASE + 0x0024 set $UART_LCR_VAL = *(unsigned short*)$UART_LCR printf "Showing UART Registers at 0x%X\n", $UART_BASE set *(unsigned short*)$UART_LCR = $UART_LCR_VAL & 0xF7 printf " RBR: " x/1th $UART_RBR printf " IER: " x/1th $UART_IER set *(unsigned short*)$UART_LCR = $UART_LCR_VAL | 0x80 printf " DLL: " x/1th $UART_DLL printf " DLH: " x/1th $UART_DLH set *(unsigned short*)$UART_LCR = $UART_LCR_VAL if $UART_DESTROY printf " IIR: " x/1th $UART_IIR else printf " IIR: <skipped destructive read>" end printf " LCR: " x/1th $UART_LCR printf " MCR: " x/1th $UART_MCR if $UART_DESTROY printf " LSR: " x/1th $UART_LSR else printf " LSR: <skipped destructive read>" end printf " SCR: " x/1th $UART_SCR printf " GCTL: " x/1th $UART_GCTL end define info-uart0 set $UART0_BASE = 0xFFC00400 info-uart $UART0_BASE ($argc > 0) end define info-uart1 set $UART1_BASE = 0xFFC02000 info-uart $UART1_BASE ($argc > 0) end
The kernel stores all of its printk() output in a circular buffer, so displaying this buffer properly requires a bit more work than just writing it as a string from the start.
define dump-dmesg set $start = log_start - logged_chars set $end = log_end set $buf = log_buf set $mask = log_buf_len - 1 while ($start != $end) set $c = $buf[$start & $mask] set $start = $start + 1 printf "%c", $c end printf "\n" end
lsmod were orginally written by linsyssoft.com, and are released under the GPL. They do the same as their run time equivilents. List the process names/numbers, list the process table, and list the installed modules.
define psname if $arg0 == 0 set $athread = init_tasks else set $athread = pidhash[(($arg0 >> 8) ^ $arg0) & 1023] end if $athread != 0 while $athread->pid != $arg0 && $athread != 0 set $athread = $athread->hash_next end if $athread != 0 printf "%d %s\n", $arg0, (char*)$athread->comm end end end
define ps set $initthread = init_tasks set $athread = init_tasks printf "%d %s\n", $athread->pid, (char*)($athread->comm) set $athread = $athread->next_task while $athread != ($initthread) if ($athread->pid) != (0) printf "%d %s\n", $athread->pid, (char*)$athread->comm end set $athread = $athread->next_task end end
define lsmod set $mod = (struct module*)module_list # the last module is the kernel, ignore it while $mod != &kernel_module printf "%p\t%s\n", (long)$mod, ($mod)->name set $mod = $mod->next end end