1# 2# This file contains a few gdb macros (user defined commands) to extract 3# useful information from kernel crashdump (kdump) like stack traces of 4# all the processes or a particular process and trapinfo. 5# 6# These macros can be used by copying this file in .gdbinit (put in home 7# directory or current directory) or by invoking gdb command with 8# --command=<command-file-name> option 9# 10# Credits: 11# Alexander Nyberg <alexn@telia.com> 12# V Srivatsa <vatsa@in.ibm.com> 13# Maneesh Soni <maneesh@in.ibm.com> 14# 15 16define bttnobp 17 set $tasks_off=((size_t)&((struct task_struct *)0)->tasks) 18 set $pid_off=((size_t)&((struct task_struct *)0)->pids[1].pid_list.next) 19 set $init_t=&init_task 20 set $next_t=(((char *)($init_t->tasks).next) - $tasks_off) 21 while ($next_t != $init_t) 22 set $next_t=(struct task_struct *)$next_t 23 printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm 24 printf "===================\n" 25 set var $stackp = $next_t.thread.esp 26 set var $stack_top = ($stackp & ~4095) + 4096 27 28 while ($stackp < $stack_top) 29 if (*($stackp) > _stext && *($stackp) < _sinittext) 30 info symbol *($stackp) 31 end 32 set $stackp += 4 33 end 34 set $next_th=(((char *)$next_t->pids[1].pid_list.next) - $pid_off) 35 while ($next_th != $next_t) 36 set $next_th=(struct task_struct *)$next_th 37 printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm 38 printf "===================\n" 39 set var $stackp = $next_t.thread.esp 40 set var $stack_top = ($stackp & ~4095) + 4096 41 42 while ($stackp < $stack_top) 43 if (*($stackp) > _stext && *($stackp) < _sinittext) 44 info symbol *($stackp) 45 end 46 set $stackp += 4 47 end 48 set $next_th=(((char *)$next_th->pids[1].pid_list.next) - $pid_off) 49 end 50 set $next_t=(char *)($next_t->tasks.next) - $tasks_off 51 end 52end 53document bttnobp 54 dump all thread stack traces on a kernel compiled with !CONFIG_FRAME_POINTER 55end 56 57define btt 58 set $tasks_off=((size_t)&((struct task_struct *)0)->tasks) 59 set $pid_off=((size_t)&((struct task_struct *)0)->pids[1].pid_list.next) 60 set $init_t=&init_task 61 set $next_t=(((char *)($init_t->tasks).next) - $tasks_off) 62 while ($next_t != $init_t) 63 set $next_t=(struct task_struct *)$next_t 64 printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm 65 printf "===================\n" 66 set var $stackp = $next_t.thread.esp 67 set var $stack_top = ($stackp & ~4095) + 4096 68 set var $stack_bot = ($stackp & ~4095) 69 70 set $stackp = *($stackp) 71 while (($stackp < $stack_top) && ($stackp > $stack_bot)) 72 set var $addr = *($stackp + 4) 73 info symbol $addr 74 set $stackp = *($stackp) 75 end 76 77 set $next_th=(((char *)$next_t->pids[1].pid_list.next) - $pid_off) 78 while ($next_th != $next_t) 79 set $next_th=(struct task_struct *)$next_th 80 printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm 81 printf "===================\n" 82 set var $stackp = $next_t.thread.esp 83 set var $stack_top = ($stackp & ~4095) + 4096 84 set var $stack_bot = ($stackp & ~4095) 85 86 set $stackp = *($stackp) 87 while (($stackp < $stack_top) && ($stackp > $stack_bot)) 88 set var $addr = *($stackp + 4) 89 info symbol $addr 90 set $stackp = *($stackp) 91 end 92 set $next_th=(((char *)$next_th->pids[1].pid_list.next) - $pid_off) 93 end 94 set $next_t=(char *)($next_t->tasks.next) - $tasks_off 95 end 96end 97document btt 98 dump all thread stack traces on a kernel compiled with CONFIG_FRAME_POINTER 99end 100 101define btpid 102 set var $pid = $arg0 103 set $tasks_off=((size_t)&((struct task_struct *)0)->tasks) 104 set $pid_off=((size_t)&((struct task_struct *)0)->pids[1].pid_list.next) 105 set $init_t=&init_task 106 set $next_t=(((char *)($init_t->tasks).next) - $tasks_off) 107 set var $pid_task = 0 108 109 while ($next_t != $init_t) 110 set $next_t=(struct task_struct *)$next_t 111 112 if ($next_t.pid == $pid) 113 set $pid_task = $next_t 114 end 115 116 set $next_th=(((char *)$next_t->pids[1].pid_list.next) - $pid_off) 117 while ($next_th != $next_t) 118 set $next_th=(struct task_struct *)$next_th 119 if ($next_th.pid == $pid) 120 set $pid_task = $next_th 121 end 122 set $next_th=(((char *)$next_th->pids[1].pid_list.next) - $pid_off) 123 end 124 set $next_t=(char *)($next_t->tasks.next) - $tasks_off 125 end 126 127 printf "\npid %d; comm %s:\n", $pid_task.pid, $pid_task.comm 128 printf "===================\n" 129 set var $stackp = $pid_task.thread.esp 130 set var $stack_top = ($stackp & ~4095) + 4096 131 set var $stack_bot = ($stackp & ~4095) 132 133 set $stackp = *($stackp) 134 while (($stackp < $stack_top) && ($stackp > $stack_bot)) 135 set var $addr = *($stackp + 4) 136 info symbol $addr 137 set $stackp = *($stackp) 138 end 139end 140document btpid 141 backtrace of pid 142end 143 144 145define trapinfo 146 set var $pid = $arg0 147 set $tasks_off=((size_t)&((struct task_struct *)0)->tasks) 148 set $pid_off=((size_t)&((struct task_struct *)0)->pids[1].pid_list.next) 149 set $init_t=&init_task 150 set $next_t=(((char *)($init_t->tasks).next) - $tasks_off) 151 set var $pid_task = 0 152 153 while ($next_t != $init_t) 154 set $next_t=(struct task_struct *)$next_t 155 156 if ($next_t.pid == $pid) 157 set $pid_task = $next_t 158 end 159 160 set $next_th=(((char *)$next_t->pids[1].pid_list.next) - $pid_off) 161 while ($next_th != $next_t) 162 set $next_th=(struct task_struct *)$next_th 163 if ($next_th.pid == $pid) 164 set $pid_task = $next_th 165 end 166 set $next_th=(((char *)$next_th->pids[1].pid_list.next) - $pid_off) 167 end 168 set $next_t=(char *)($next_t->tasks.next) - $tasks_off 169 end 170 171 printf "Trapno %ld, cr2 0x%lx, error_code %ld\n", $pid_task.thread.trap_no, \ 172 $pid_task.thread.cr2, $pid_task.thread.error_code 173 174end 175document trapinfo 176 Run info threads and lookup pid of thread #1 177 'trapinfo <pid>' will tell you by which trap & possibly 178 address the kernel panicked. 179end 180 181 182define dmesg 183 set $i = 0 184 set $end_idx = (log_end - 1) & (log_buf_len - 1) 185 186 while ($i < logged_chars) 187 set $idx = (log_end - 1 - logged_chars + $i) & (log_buf_len - 1) 188 189 if ($idx + 100 <= $end_idx) || \ 190 ($end_idx <= $idx && $idx + 100 < log_buf_len) 191 printf "%.100s", &log_buf[$idx] 192 set $i = $i + 100 193 else 194 printf "%c", log_buf[$idx] 195 set $i = $i + 1 196 end 197 end 198end 199document dmesg 200 print the kernel ring buffer 201end 202