Vivek Goyal | b089f4a | 2005-06-25 14:58:15 -0700 | [diff] [blame] | 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 | |
| 16 | define bttnobp |
| 17 | set $tasks_off=((size_t)&((struct task_struct *)0)->tasks) |
Corey Minyard | a0c20de | 2016-05-23 16:24:25 -0700 | [diff] [blame] | 18 | set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next) |
Vivek Goyal | b089f4a | 2005-06-25 14:58:15 -0700 | [diff] [blame] | 19 | set $init_t=&init_task |
| 20 | set $next_t=(((char *)($init_t->tasks).next) - $tasks_off) |
Corey Minyard | a0c20de | 2016-05-23 16:24:25 -0700 | [diff] [blame] | 21 | set var $stacksize = sizeof(union thread_union) |
Vivek Goyal | b089f4a | 2005-06-25 14:58:15 -0700 | [diff] [blame] | 22 | while ($next_t != $init_t) |
| 23 | set $next_t=(struct task_struct *)$next_t |
| 24 | printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm |
| 25 | printf "===================\n" |
Corey Minyard | a0c20de | 2016-05-23 16:24:25 -0700 | [diff] [blame] | 26 | set var $stackp = $next_t.thread.sp |
| 27 | set var $stack_top = ($stackp & ~($stacksize - 1)) + $stacksize |
Vivek Goyal | b089f4a | 2005-06-25 14:58:15 -0700 | [diff] [blame] | 28 | |
| 29 | while ($stackp < $stack_top) |
| 30 | if (*($stackp) > _stext && *($stackp) < _sinittext) |
| 31 | info symbol *($stackp) |
| 32 | end |
| 33 | set $stackp += 4 |
| 34 | end |
Corey Minyard | a0c20de | 2016-05-23 16:24:25 -0700 | [diff] [blame] | 35 | set $next_th=(((char *)$next_t->thread_group.next) - $pid_off) |
Vivek Goyal | b089f4a | 2005-06-25 14:58:15 -0700 | [diff] [blame] | 36 | while ($next_th != $next_t) |
| 37 | set $next_th=(struct task_struct *)$next_th |
| 38 | printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm |
| 39 | printf "===================\n" |
Corey Minyard | a0c20de | 2016-05-23 16:24:25 -0700 | [diff] [blame] | 40 | set var $stackp = $next_t.thread.sp |
| 41 | set var $stack_top = ($stackp & ~($stacksize - 1)) + stacksize |
Vivek Goyal | b089f4a | 2005-06-25 14:58:15 -0700 | [diff] [blame] | 42 | |
| 43 | while ($stackp < $stack_top) |
| 44 | if (*($stackp) > _stext && *($stackp) < _sinittext) |
| 45 | info symbol *($stackp) |
| 46 | end |
| 47 | set $stackp += 4 |
| 48 | end |
Corey Minyard | a0c20de | 2016-05-23 16:24:25 -0700 | [diff] [blame] | 49 | set $next_th=(((char *)$next_th->thread_group.next) - $pid_off) |
Vivek Goyal | b089f4a | 2005-06-25 14:58:15 -0700 | [diff] [blame] | 50 | end |
| 51 | set $next_t=(char *)($next_t->tasks.next) - $tasks_off |
| 52 | end |
| 53 | end |
| 54 | document bttnobp |
| 55 | dump all thread stack traces on a kernel compiled with !CONFIG_FRAME_POINTER |
| 56 | end |
| 57 | |
Corey Minyard | a0c20de | 2016-05-23 16:24:25 -0700 | [diff] [blame] | 58 | define btthreadstack |
| 59 | set var $pid_task = $arg0 |
| 60 | |
| 61 | printf "\npid %d; comm %s:\n", $pid_task.pid, $pid_task.comm |
| 62 | printf "task struct: " |
| 63 | print $pid_task |
| 64 | printf "===================\n" |
| 65 | set var $stackp = $pid_task.thread.sp |
| 66 | set var $stacksize = sizeof(union thread_union) |
| 67 | set var $stack_top = ($stackp & ~($stacksize - 1)) + $stacksize |
| 68 | set var $stack_bot = ($stackp & ~($stacksize - 1)) |
| 69 | |
| 70 | set $stackp = *((unsigned long *) $stackp) |
| 71 | while (($stackp < $stack_top) && ($stackp > $stack_bot)) |
| 72 | set var $addr = *(((unsigned long *) $stackp) + 1) |
| 73 | info symbol $addr |
| 74 | set $stackp = *((unsigned long *) $stackp) |
| 75 | end |
| 76 | end |
| 77 | document btthreadstack |
| 78 | dump a thread stack using the given task structure pointer |
| 79 | end |
| 80 | |
| 81 | |
Vivek Goyal | b089f4a | 2005-06-25 14:58:15 -0700 | [diff] [blame] | 82 | define btt |
| 83 | set $tasks_off=((size_t)&((struct task_struct *)0)->tasks) |
Corey Minyard | a0c20de | 2016-05-23 16:24:25 -0700 | [diff] [blame] | 84 | set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next) |
Vivek Goyal | b089f4a | 2005-06-25 14:58:15 -0700 | [diff] [blame] | 85 | set $init_t=&init_task |
| 86 | set $next_t=(((char *)($init_t->tasks).next) - $tasks_off) |
| 87 | while ($next_t != $init_t) |
| 88 | set $next_t=(struct task_struct *)$next_t |
Corey Minyard | a0c20de | 2016-05-23 16:24:25 -0700 | [diff] [blame] | 89 | btthreadstack $next_t |
Vivek Goyal | b089f4a | 2005-06-25 14:58:15 -0700 | [diff] [blame] | 90 | |
Corey Minyard | a0c20de | 2016-05-23 16:24:25 -0700 | [diff] [blame] | 91 | set $next_th=(((char *)$next_t->thread_group.next) - $pid_off) |
Vivek Goyal | b089f4a | 2005-06-25 14:58:15 -0700 | [diff] [blame] | 92 | while ($next_th != $next_t) |
| 93 | set $next_th=(struct task_struct *)$next_th |
Corey Minyard | a0c20de | 2016-05-23 16:24:25 -0700 | [diff] [blame] | 94 | btthreadstack $next_th |
| 95 | set $next_th=(((char *)$next_th->thread_group.next) - $pid_off) |
Vivek Goyal | b089f4a | 2005-06-25 14:58:15 -0700 | [diff] [blame] | 96 | end |
| 97 | set $next_t=(char *)($next_t->tasks.next) - $tasks_off |
| 98 | end |
| 99 | end |
| 100 | document btt |
| 101 | dump all thread stack traces on a kernel compiled with CONFIG_FRAME_POINTER |
| 102 | end |
| 103 | |
| 104 | define btpid |
| 105 | set var $pid = $arg0 |
| 106 | set $tasks_off=((size_t)&((struct task_struct *)0)->tasks) |
Corey Minyard | a0c20de | 2016-05-23 16:24:25 -0700 | [diff] [blame] | 107 | set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next) |
Vivek Goyal | b089f4a | 2005-06-25 14:58:15 -0700 | [diff] [blame] | 108 | set $init_t=&init_task |
| 109 | set $next_t=(((char *)($init_t->tasks).next) - $tasks_off) |
| 110 | set var $pid_task = 0 |
| 111 | |
| 112 | while ($next_t != $init_t) |
| 113 | set $next_t=(struct task_struct *)$next_t |
| 114 | |
| 115 | if ($next_t.pid == $pid) |
| 116 | set $pid_task = $next_t |
| 117 | end |
| 118 | |
Corey Minyard | a0c20de | 2016-05-23 16:24:25 -0700 | [diff] [blame] | 119 | set $next_th=(((char *)$next_t->thread_group.next) - $pid_off) |
Vivek Goyal | b089f4a | 2005-06-25 14:58:15 -0700 | [diff] [blame] | 120 | while ($next_th != $next_t) |
| 121 | set $next_th=(struct task_struct *)$next_th |
| 122 | if ($next_th.pid == $pid) |
| 123 | set $pid_task = $next_th |
| 124 | end |
Corey Minyard | a0c20de | 2016-05-23 16:24:25 -0700 | [diff] [blame] | 125 | set $next_th=(((char *)$next_th->thread_group.next) - $pid_off) |
Vivek Goyal | b089f4a | 2005-06-25 14:58:15 -0700 | [diff] [blame] | 126 | end |
| 127 | set $next_t=(char *)($next_t->tasks.next) - $tasks_off |
| 128 | end |
| 129 | |
Corey Minyard | a0c20de | 2016-05-23 16:24:25 -0700 | [diff] [blame] | 130 | btthreadstack $pid_task |
Vivek Goyal | b089f4a | 2005-06-25 14:58:15 -0700 | [diff] [blame] | 131 | end |
| 132 | document btpid |
| 133 | backtrace of pid |
| 134 | end |
| 135 | |
| 136 | |
| 137 | define trapinfo |
| 138 | set var $pid = $arg0 |
| 139 | set $tasks_off=((size_t)&((struct task_struct *)0)->tasks) |
Corey Minyard | a0c20de | 2016-05-23 16:24:25 -0700 | [diff] [blame] | 140 | set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next) |
Vivek Goyal | b089f4a | 2005-06-25 14:58:15 -0700 | [diff] [blame] | 141 | set $init_t=&init_task |
| 142 | set $next_t=(((char *)($init_t->tasks).next) - $tasks_off) |
| 143 | set var $pid_task = 0 |
| 144 | |
| 145 | while ($next_t != $init_t) |
| 146 | set $next_t=(struct task_struct *)$next_t |
| 147 | |
| 148 | if ($next_t.pid == $pid) |
| 149 | set $pid_task = $next_t |
| 150 | end |
| 151 | |
Corey Minyard | a0c20de | 2016-05-23 16:24:25 -0700 | [diff] [blame] | 152 | set $next_th=(((char *)$next_t->thread_group.next) - $pid_off) |
Vivek Goyal | b089f4a | 2005-06-25 14:58:15 -0700 | [diff] [blame] | 153 | while ($next_th != $next_t) |
| 154 | set $next_th=(struct task_struct *)$next_th |
| 155 | if ($next_th.pid == $pid) |
| 156 | set $pid_task = $next_th |
| 157 | end |
Corey Minyard | a0c20de | 2016-05-23 16:24:25 -0700 | [diff] [blame] | 158 | set $next_th=(((char *)$next_th->thread_group.next) - $pid_off) |
Vivek Goyal | b089f4a | 2005-06-25 14:58:15 -0700 | [diff] [blame] | 159 | end |
| 160 | set $next_t=(char *)($next_t->tasks.next) - $tasks_off |
| 161 | end |
| 162 | |
| 163 | printf "Trapno %ld, cr2 0x%lx, error_code %ld\n", $pid_task.thread.trap_no, \ |
| 164 | $pid_task.thread.cr2, $pid_task.thread.error_code |
| 165 | |
| 166 | end |
| 167 | document trapinfo |
| 168 | Run info threads and lookup pid of thread #1 |
| 169 | 'trapinfo <pid>' will tell you by which trap & possibly |
Lee Revell | f18190b | 2006-06-26 18:30:00 +0200 | [diff] [blame] | 170 | address the kernel panicked. |
Vivek Goyal | b089f4a | 2005-06-25 14:58:15 -0700 | [diff] [blame] | 171 | end |
Akinobu Mita | 8428cfe | 2006-01-11 12:17:30 -0800 | [diff] [blame] | 172 | |
Corey Minyard | d8bae33 | 2016-06-03 14:55:36 -0700 | [diff] [blame] | 173 | define dump_log_idx |
| 174 | set $idx = $arg0 |
| 175 | if ($argc > 1) |
| 176 | set $prev_flags = $arg1 |
| 177 | else |
| 178 | set $prev_flags = 0 |
| 179 | end |
| 180 | set $msg = ((struct printk_log *) (log_buf + $idx)) |
| 181 | set $prefix = 1 |
| 182 | set $newline = 1 |
| 183 | set $log = log_buf + $idx + sizeof(*$msg) |
| 184 | |
| 185 | # prev & LOG_CONT && !(msg->flags & LOG_PREIX) |
| 186 | if (($prev_flags & 8) && !($msg->flags & 4)) |
| 187 | set $prefix = 0 |
| 188 | end |
| 189 | |
| 190 | # msg->flags & LOG_CONT |
| 191 | if ($msg->flags & 8) |
| 192 | # (prev & LOG_CONT && !(prev & LOG_NEWLINE)) |
| 193 | if (($prev_flags & 8) && !($prev_flags & 2)) |
| 194 | set $prefix = 0 |
| 195 | end |
| 196 | # (!(msg->flags & LOG_NEWLINE)) |
| 197 | if (!($msg->flags & 2)) |
| 198 | set $newline = 0 |
| 199 | end |
| 200 | end |
| 201 | |
| 202 | if ($prefix) |
| 203 | printf "[%5lu.%06lu] ", $msg->ts_nsec / 1000000000, $msg->ts_nsec % 1000000000 |
| 204 | end |
| 205 | if ($msg->text_len != 0) |
| 206 | eval "printf \"%%%d.%ds\", $log", $msg->text_len, $msg->text_len |
| 207 | end |
| 208 | if ($newline) |
| 209 | printf "\n" |
| 210 | end |
| 211 | if ($msg->dict_len > 0) |
| 212 | set $dict = $log + $msg->text_len |
| 213 | set $idx = 0 |
| 214 | set $line = 1 |
| 215 | while ($idx < $msg->dict_len) |
| 216 | if ($line) |
| 217 | printf " " |
| 218 | set $line = 0 |
| 219 | end |
| 220 | set $c = $dict[$idx] |
| 221 | if ($c == '\0') |
| 222 | printf "\n" |
| 223 | set $line = 1 |
| 224 | else |
| 225 | if ($c < ' ' || $c >= 127 || $c == '\\') |
| 226 | printf "\\x%02x", $c |
| 227 | else |
| 228 | printf "%c", $c |
| 229 | end |
| 230 | end |
| 231 | set $idx = $idx + 1 |
| 232 | end |
| 233 | printf "\n" |
| 234 | end |
| 235 | end |
| 236 | document dump_log_idx |
| 237 | Dump a single log given its index in the log buffer. The first |
| 238 | parameter is the index into log_buf, the second is optional and |
| 239 | specified the previous log buffer's flags, used for properly |
| 240 | formatting continued lines. |
| 241 | end |
Akinobu Mita | 8428cfe | 2006-01-11 12:17:30 -0800 | [diff] [blame] | 242 | |
| 243 | define dmesg |
Corey Minyard | d8bae33 | 2016-06-03 14:55:36 -0700 | [diff] [blame] | 244 | set $i = log_first_idx |
| 245 | set $end_idx = log_first_idx |
| 246 | set $prev_flags = 0 |
Akinobu Mita | 8428cfe | 2006-01-11 12:17:30 -0800 | [diff] [blame] | 247 | |
Corey Minyard | d8bae33 | 2016-06-03 14:55:36 -0700 | [diff] [blame] | 248 | while (1) |
| 249 | set $msg = ((struct printk_log *) (log_buf + $i)) |
| 250 | if ($msg->len == 0) |
| 251 | set $i = 0 |
Akinobu Mita | 8428cfe | 2006-01-11 12:17:30 -0800 | [diff] [blame] | 252 | else |
Corey Minyard | d8bae33 | 2016-06-03 14:55:36 -0700 | [diff] [blame] | 253 | dump_log_idx $i $prev_flags |
| 254 | set $i = $i + $msg->len |
| 255 | set $prev_flags = $msg->flags |
| 256 | end |
| 257 | if ($i == $end_idx) |
| 258 | loop_break |
Akinobu Mita | 8428cfe | 2006-01-11 12:17:30 -0800 | [diff] [blame] | 259 | end |
| 260 | end |
| 261 | end |
| 262 | document dmesg |
| 263 | print the kernel ring buffer |
| 264 | end |