1 # 1 # 2 # This file contains a few gdb macros (user de 2 # This file contains a few gdb macros (user defined commands) to extract 3 # useful information from kernel crashdump (kd 3 # useful information from kernel crashdump (kdump) like stack traces of 4 # all the processes or a particular process an 4 # all the processes or a particular process and trapinfo. 5 # 5 # 6 # These macros can be used by copying this fil 6 # These macros can be used by copying this file in .gdbinit (put in home 7 # directory or current directory) or by invoki 7 # directory or current directory) or by invoking gdb command with 8 # --command=<command-file-name> option 8 # --command=<command-file-name> option 9 # 9 # 10 # Credits: 10 # Credits: 11 # Alexander Nyberg <alexn@telia.com> 11 # Alexander Nyberg <alexn@telia.com> 12 # V Srivatsa <vatsa@in.ibm.com> 12 # V Srivatsa <vatsa@in.ibm.com> 13 # Maneesh Soni <maneesh@in.ibm.com> 13 # Maneesh Soni <maneesh@in.ibm.com> 14 # 14 # 15 15 16 define bttnobp 16 define bttnobp 17 set $tasks_off=((size_t)&((struct task 17 set $tasks_off=((size_t)&((struct task_struct *)0)->tasks) 18 set $pid_off=((size_t)&((struct task_s 18 set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next) 19 set $init_t=&init_task 19 set $init_t=&init_task 20 set $next_t=(((char *)($init_t->tasks) 20 set $next_t=(((char *)($init_t->tasks).next) - $tasks_off) 21 set var $stacksize = sizeof(union thre 21 set var $stacksize = sizeof(union thread_union) 22 while ($next_t != $init_t) 22 while ($next_t != $init_t) 23 set $next_t=(struct task_struc 23 set $next_t=(struct task_struct *)$next_t 24 printf "\npid %d; comm %s:\n", 24 printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm 25 printf "===================\n" 25 printf "===================\n" 26 set var $stackp = $next_t.thre 26 set var $stackp = $next_t.thread.sp 27 set var $stack_top = ($stackp 27 set var $stack_top = ($stackp & ~($stacksize - 1)) + $stacksize 28 28 29 while ($stackp < $stack_top) 29 while ($stackp < $stack_top) 30 if (*($stackp) > _stex 30 if (*($stackp) > _stext && *($stackp) < _sinittext) 31 info symbol *( 31 info symbol *($stackp) 32 end 32 end 33 set $stackp += 4 33 set $stackp += 4 34 end 34 end 35 set $next_th=(((char *)$next_t 35 set $next_th=(((char *)$next_t->thread_group.next) - $pid_off) 36 while ($next_th != $next_t) 36 while ($next_th != $next_t) 37 set $next_th=(struct t 37 set $next_th=(struct task_struct *)$next_th 38 printf "\npid %d; comm 38 printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm 39 printf "============== 39 printf "===================\n" 40 set var $stackp = $nex 40 set var $stackp = $next_t.thread.sp 41 set var $stack_top = ( 41 set var $stack_top = ($stackp & ~($stacksize - 1)) + stacksize 42 42 43 while ($stackp < $stac 43 while ($stackp < $stack_top) 44 if (*($stackp) 44 if (*($stackp) > _stext && *($stackp) < _sinittext) 45 info s 45 info symbol *($stackp) 46 end 46 end 47 set $stackp += 47 set $stackp += 4 48 end 48 end 49 set $next_th=(((char * 49 set $next_th=(((char *)$next_th->thread_group.next) - $pid_off) 50 end 50 end 51 set $next_t=(char *)($next_t-> 51 set $next_t=(char *)($next_t->tasks.next) - $tasks_off 52 end 52 end 53 end 53 end 54 document bttnobp 54 document bttnobp 55 dump all thread stack traces on a kern 55 dump all thread stack traces on a kernel compiled with !CONFIG_FRAME_POINTER 56 end 56 end 57 57 58 define btthreadstack 58 define btthreadstack 59 set var $pid_task = $arg0 59 set var $pid_task = $arg0 60 60 61 printf "\npid %d; comm %s:\n", $pid_ta 61 printf "\npid %d; comm %s:\n", $pid_task.pid, $pid_task.comm 62 printf "task struct: " 62 printf "task struct: " 63 print $pid_task 63 print $pid_task 64 printf "===================\n" 64 printf "===================\n" 65 set var $stackp = $pid_task.thread.sp 65 set var $stackp = $pid_task.thread.sp 66 set var $stacksize = sizeof(union thre 66 set var $stacksize = sizeof(union thread_union) 67 set var $stack_top = ($stackp & ~($sta 67 set var $stack_top = ($stackp & ~($stacksize - 1)) + $stacksize 68 set var $stack_bot = ($stackp & ~($sta 68 set var $stack_bot = ($stackp & ~($stacksize - 1)) 69 69 70 set $stackp = *((unsigned long *) $sta 70 set $stackp = *((unsigned long *) $stackp) 71 while (($stackp < $stack_top) && ($sta 71 while (($stackp < $stack_top) && ($stackp > $stack_bot)) 72 set var $addr = *(((unsigned l 72 set var $addr = *(((unsigned long *) $stackp) + 1) 73 info symbol $addr 73 info symbol $addr 74 set $stackp = *((unsigned long 74 set $stackp = *((unsigned long *) $stackp) 75 end 75 end 76 end 76 end 77 document btthreadstack 77 document btthreadstack 78 dump a thread stack using the given t 78 dump a thread stack using the given task structure pointer 79 end 79 end 80 80 81 81 82 define btt 82 define btt 83 set $tasks_off=((size_t)&((struct task 83 set $tasks_off=((size_t)&((struct task_struct *)0)->tasks) 84 set $pid_off=((size_t)&((struct task_s 84 set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next) 85 set $init_t=&init_task 85 set $init_t=&init_task 86 set $next_t=(((char *)($init_t->tasks) 86 set $next_t=(((char *)($init_t->tasks).next) - $tasks_off) 87 while ($next_t != $init_t) 87 while ($next_t != $init_t) 88 set $next_t=(struct task_struc 88 set $next_t=(struct task_struct *)$next_t 89 btthreadstack $next_t 89 btthreadstack $next_t 90 90 91 set $next_th=(((char *)$next_t 91 set $next_th=(((char *)$next_t->thread_group.next) - $pid_off) 92 while ($next_th != $next_t) 92 while ($next_th != $next_t) 93 set $next_th=(struct t 93 set $next_th=(struct task_struct *)$next_th 94 btthreadstack $next_th 94 btthreadstack $next_th 95 set $next_th=(((char * 95 set $next_th=(((char *)$next_th->thread_group.next) - $pid_off) 96 end 96 end 97 set $next_t=(char *)($next_t-> 97 set $next_t=(char *)($next_t->tasks.next) - $tasks_off 98 end 98 end 99 end 99 end 100 document btt 100 document btt 101 dump all thread stack traces on a kern 101 dump all thread stack traces on a kernel compiled with CONFIG_FRAME_POINTER 102 end 102 end 103 103 104 define btpid 104 define btpid 105 set var $pid = $arg0 105 set var $pid = $arg0 106 set $tasks_off=((size_t)&((struct task 106 set $tasks_off=((size_t)&((struct task_struct *)0)->tasks) 107 set $pid_off=((size_t)&((struct task_s 107 set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next) 108 set $init_t=&init_task 108 set $init_t=&init_task 109 set $next_t=(((char *)($init_t->tasks) 109 set $next_t=(((char *)($init_t->tasks).next) - $tasks_off) 110 set var $pid_task = 0 110 set var $pid_task = 0 111 111 112 while ($next_t != $init_t) 112 while ($next_t != $init_t) 113 set $next_t=(struct task_struc 113 set $next_t=(struct task_struct *)$next_t 114 114 115 if ($next_t.pid == $pid) 115 if ($next_t.pid == $pid) 116 set $pid_task = $next_ 116 set $pid_task = $next_t 117 end 117 end 118 118 119 set $next_th=(((char *)$next_t 119 set $next_th=(((char *)$next_t->thread_group.next) - $pid_off) 120 while ($next_th != $next_t) 120 while ($next_th != $next_t) 121 set $next_th=(struct t 121 set $next_th=(struct task_struct *)$next_th 122 if ($next_th.pid == $p 122 if ($next_th.pid == $pid) 123 set $pid_task 123 set $pid_task = $next_th 124 end 124 end 125 set $next_th=(((char * 125 set $next_th=(((char *)$next_th->thread_group.next) - $pid_off) 126 end 126 end 127 set $next_t=(char *)($next_t-> 127 set $next_t=(char *)($next_t->tasks.next) - $tasks_off 128 end 128 end 129 129 130 btthreadstack $pid_task 130 btthreadstack $pid_task 131 end 131 end 132 document btpid 132 document btpid 133 backtrace of pid 133 backtrace of pid 134 end 134 end 135 135 136 136 137 define trapinfo 137 define trapinfo 138 set var $pid = $arg0 138 set var $pid = $arg0 139 set $tasks_off=((size_t)&((struct task 139 set $tasks_off=((size_t)&((struct task_struct *)0)->tasks) 140 set $pid_off=((size_t)&((struct task_s 140 set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next) 141 set $init_t=&init_task 141 set $init_t=&init_task 142 set $next_t=(((char *)($init_t->tasks) 142 set $next_t=(((char *)($init_t->tasks).next) - $tasks_off) 143 set var $pid_task = 0 143 set var $pid_task = 0 144 144 145 while ($next_t != $init_t) 145 while ($next_t != $init_t) 146 set $next_t=(struct task_struc 146 set $next_t=(struct task_struct *)$next_t 147 147 148 if ($next_t.pid == $pid) 148 if ($next_t.pid == $pid) 149 set $pid_task = $next_ 149 set $pid_task = $next_t 150 end 150 end 151 151 152 set $next_th=(((char *)$next_t 152 set $next_th=(((char *)$next_t->thread_group.next) - $pid_off) 153 while ($next_th != $next_t) 153 while ($next_th != $next_t) 154 set $next_th=(struct t 154 set $next_th=(struct task_struct *)$next_th 155 if ($next_th.pid == $p 155 if ($next_th.pid == $pid) 156 set $pid_task 156 set $pid_task = $next_th 157 end 157 end 158 set $next_th=(((char * 158 set $next_th=(((char *)$next_th->thread_group.next) - $pid_off) 159 end 159 end 160 set $next_t=(char *)($next_t-> 160 set $next_t=(char *)($next_t->tasks.next) - $tasks_off 161 end 161 end 162 162 163 printf "Trapno %ld, cr2 0x%lx, error_c 163 printf "Trapno %ld, cr2 0x%lx, error_code %ld\n", $pid_task.thread.trap_no, \ 164 $pid_task.thre 164 $pid_task.thread.cr2, $pid_task.thread.error_code 165 165 166 end 166 end 167 document trapinfo 167 document trapinfo 168 Run info threads and lookup pid of thr 168 Run info threads and lookup pid of thread #1 169 'trapinfo <pid>' will tell you by whic 169 'trapinfo <pid>' will tell you by which trap & possibly 170 address the kernel panicked. 170 address the kernel panicked. 171 end 171 end 172 172 173 define dump_record !! 173 define dump_log_idx 174 set var $desc = $arg0 !! 174 set $idx = $arg0 175 set var $info = $arg1 !! 175 if ($argc > 1) 176 if ($argc > 2) !! 176 set $prev_flags = $arg1 177 set var $prev_flags = $arg2 << 178 else 177 else 179 set var $prev_flags = 0 !! 178 set $prev_flags = 0 180 end 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) 181 184 182 set var $prefix = 1 !! 185 # prev & LOG_CONT && !(msg->flags & LOG_PREIX) 183 set var $newline = 1 !! 186 if (($prev_flags & 8) && !($msg->flags & 4)) 184 !! 187 set $prefix = 0 185 set var $begin = $desc->text_blk_lpos. << 186 set var $next = $desc->text_blk_lpos.n << 187 << 188 # handle data-less record << 189 if ($begin & 1) << 190 set var $text_len = 0 << 191 set var $log = "" << 192 else << 193 # handle wrapping data block << 194 if ($begin > $next) << 195 set var $begin = 0 << 196 end << 197 << 198 # skip over descriptor id << 199 set var $begin = $begin + size << 200 << 201 # handle truncated message << 202 if ($next - $begin < $info->te << 203 set var $text_len = $n << 204 else << 205 set var $text_len = $i << 206 end << 207 << 208 set var $log = &prb->text_data << 209 end << 210 << 211 # prev & LOG_CONT && !(info->flags & L << 212 if (($prev_flags & 8) && !($info->flag << 213 set var $prefix = 0 << 214 end 188 end 215 189 216 # info->flags & LOG_CONT !! 190 # msg->flags & LOG_CONT 217 if ($info->flags & 8) !! 191 if ($msg->flags & 8) 218 # (prev & LOG_CONT && !(prev & 192 # (prev & LOG_CONT && !(prev & LOG_NEWLINE)) 219 if (($prev_flags & 8) && !($pr 193 if (($prev_flags & 8) && !($prev_flags & 2)) 220 set var $prefix = 0 !! 194 set $prefix = 0 221 end 195 end 222 # (!(info->flags & LOG_NEWLINE !! 196 # (!(msg->flags & LOG_NEWLINE)) 223 if (!($info->flags & 2)) !! 197 if (!($msg->flags & 2)) 224 set var $newline = 0 !! 198 set $newline = 0 225 end 199 end 226 end 200 end 227 201 228 if ($prefix) 202 if ($prefix) 229 printf "[%5lu.%06lu] ", $info- !! 203 printf "[%5lu.%06lu] ", $msg->ts_nsec / 1000000000, $msg->ts_nsec % 1000000000 230 end 204 end 231 if ($text_len) !! 205 if ($msg->text_len != 0) 232 eval "printf \"%%%d.%ds\", $lo !! 206 eval "printf \"%%%d.%ds\", $log", $msg->text_len, $msg->text_len 233 end 207 end 234 if ($newline) 208 if ($newline) 235 printf "\n" 209 printf "\n" 236 end 210 end 237 !! 211 if ($msg->dict_len > 0) 238 # handle dictionary data !! 212 set $dict = $log + $msg->text_len 239 !! 213 set $idx = 0 240 set var $dict = &$info->dev_info.subsy !! 214 set $line = 1 241 set var $dict_len = sizeof($info->dev_ !! 215 while ($idx < $msg->dict_len) 242 if ($dict[0] != '\0') !! 216 if ($line) 243 printf " SUBSYSTEM=" !! 217 printf " " 244 set var $idx = 0 !! 218 set $line = 0 245 while ($idx < $dict_len) << 246 set var $c = $dict[$id << 247 if ($c == '\0') << 248 loop_break << 249 else << 250 if ($c < ' ' | << 251 printf << 252 else << 253 printf << 254 end << 255 end 219 end 256 set var $idx = $idx + !! 220 set $c = $dict[$idx] 257 end << 258 printf "\n" << 259 end << 260 << 261 set var $dict = &$info->dev_info.devic << 262 set var $dict_len = sizeof($info->dev_ << 263 if ($dict[0] != '\0') << 264 printf " DEVICE=" << 265 set var $idx = 0 << 266 while ($idx < $dict_len) << 267 set var $c = $dict[$id << 268 if ($c == '\0') 221 if ($c == '\0') 269 loop_break !! 222 printf "\n" >> 223 set $line = 1 270 else 224 else 271 if ($c < ' ' | 225 if ($c < ' ' || $c >= 127 || $c == '\\') 272 printf 226 printf "\\x%02x", $c 273 else 227 else 274 printf 228 printf "%c", $c 275 end 229 end 276 end 230 end 277 set var $idx = $idx + !! 231 set $idx = $idx + 1 278 end 232 end 279 printf "\n" 233 printf "\n" 280 end 234 end 281 end 235 end 282 document dump_record !! 236 document dump_log_idx 283 Dump a single record. The first parame !! 237 Dump a single log given its index in the log buffer. The first 284 the second parameter is the info, the !! 238 parameter is the index into log_buf, the second is optional and 285 optional and specifies the previous re !! 239 specified the previous log buffer's flags, used for properly 286 properly formatting continued lines. !! 240 formatting continued lines. 287 end 241 end 288 242 289 define dmesg 243 define dmesg 290 # definitions from kernel/printk/print !! 244 set $i = log_first_idx 291 set var $desc_committed = 1 !! 245 set $end_idx = log_first_idx 292 set var $desc_finalized = 2 !! 246 set $prev_flags = 0 293 set var $desc_sv_bits = sizeof(long) * << 294 set var $desc_flags_shift = $desc_sv_b << 295 set var $desc_flags_mask = 3 << $desc_ << 296 set var $id_mask = ~$desc_flags_mask << 297 << 298 set var $desc_count = 1U << prb->desc_ << 299 set var $prev_flags = 0 << 300 << 301 set var $id = prb->desc_ring.tail_id.c << 302 set var $end_id = prb->desc_ring.head_ << 303 247 304 while (1) 248 while (1) 305 set var $desc = &prb->desc_rin !! 249 set $msg = ((struct printk_log *) (log_buf + $i)) 306 set var $info = &prb->desc_rin !! 250 if ($msg->len == 0) 307 !! 251 set $i = 0 308 # skip non-committed record !! 252 else 309 set var $state = 3 & ($desc->s !! 253 dump_log_idx $i $prev_flags 310 if ($state == $desc_committed !! 254 set $i = $i + $msg->len 311 dump_record $desc $inf !! 255 set $prev_flags = $msg->flags 312 set var $prev_flags = << 313 end 256 end 314 !! 257 if ($i == $end_idx) 315 if ($id == $end_id) << 316 loop_break 258 loop_break 317 end 259 end 318 set var $id = ($id + 1) & $id_ << 319 end 260 end 320 end 261 end 321 document dmesg 262 document dmesg 322 print the kernel ring buffer 263 print the kernel ring buffer 323 end 264 end
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.