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_record 174 set var $desc = $arg0 174 set var $desc = $arg0 175 set var $info = $arg1 175 set var $info = $arg1 176 if ($argc > 2) 176 if ($argc > 2) 177 set var $prev_flags = $arg2 177 set var $prev_flags = $arg2 178 else 178 else 179 set var $prev_flags = 0 179 set var $prev_flags = 0 180 end 180 end 181 181 182 set var $prefix = 1 182 set var $prefix = 1 183 set var $newline = 1 183 set var $newline = 1 184 184 185 set var $begin = $desc->text_blk_lpos. 185 set var $begin = $desc->text_blk_lpos.begin % (1U << prb->text_data_ring.size_bits) 186 set var $next = $desc->text_blk_lpos.n 186 set var $next = $desc->text_blk_lpos.next % (1U << prb->text_data_ring.size_bits) 187 187 188 # handle data-less record 188 # handle data-less record 189 if ($begin & 1) 189 if ($begin & 1) 190 set var $text_len = 0 190 set var $text_len = 0 191 set var $log = "" 191 set var $log = "" 192 else 192 else 193 # handle wrapping data block 193 # handle wrapping data block 194 if ($begin > $next) 194 if ($begin > $next) 195 set var $begin = 0 195 set var $begin = 0 196 end 196 end 197 197 198 # skip over descriptor id 198 # skip over descriptor id 199 set var $begin = $begin + size 199 set var $begin = $begin + sizeof(long) 200 200 201 # handle truncated message 201 # handle truncated message 202 if ($next - $begin < $info->te 202 if ($next - $begin < $info->text_len) 203 set var $text_len = $n 203 set var $text_len = $next - $begin 204 else 204 else 205 set var $text_len = $i 205 set var $text_len = $info->text_len 206 end 206 end 207 207 208 set var $log = &prb->text_data 208 set var $log = &prb->text_data_ring.data[$begin] 209 end 209 end 210 210 211 # prev & LOG_CONT && !(info->flags & L 211 # prev & LOG_CONT && !(info->flags & LOG_PREIX) 212 if (($prev_flags & 8) && !($info->flag 212 if (($prev_flags & 8) && !($info->flags & 4)) 213 set var $prefix = 0 213 set var $prefix = 0 214 end 214 end 215 215 216 # info->flags & LOG_CONT 216 # info->flags & LOG_CONT 217 if ($info->flags & 8) 217 if ($info->flags & 8) 218 # (prev & LOG_CONT && !(prev & 218 # (prev & LOG_CONT && !(prev & LOG_NEWLINE)) 219 if (($prev_flags & 8) && !($pr 219 if (($prev_flags & 8) && !($prev_flags & 2)) 220 set var $prefix = 0 220 set var $prefix = 0 221 end 221 end 222 # (!(info->flags & LOG_NEWLINE 222 # (!(info->flags & LOG_NEWLINE)) 223 if (!($info->flags & 2)) 223 if (!($info->flags & 2)) 224 set var $newline = 0 224 set var $newline = 0 225 end 225 end 226 end 226 end 227 227 228 if ($prefix) 228 if ($prefix) 229 printf "[%5lu.%06lu] ", $info- 229 printf "[%5lu.%06lu] ", $info->ts_nsec / 1000000000, $info->ts_nsec % 1000000000 230 end 230 end 231 if ($text_len) 231 if ($text_len) 232 eval "printf \"%%%d.%ds\", $lo 232 eval "printf \"%%%d.%ds\", $log", $text_len, $text_len 233 end 233 end 234 if ($newline) 234 if ($newline) 235 printf "\n" 235 printf "\n" 236 end 236 end 237 237 238 # handle dictionary data 238 # handle dictionary data 239 239 240 set var $dict = &$info->dev_info.subsy 240 set var $dict = &$info->dev_info.subsystem[0] 241 set var $dict_len = sizeof($info->dev_ 241 set var $dict_len = sizeof($info->dev_info.subsystem) 242 if ($dict[0] != '\0') 242 if ($dict[0] != '\0') 243 printf " SUBSYSTEM=" 243 printf " SUBSYSTEM=" 244 set var $idx = 0 244 set var $idx = 0 245 while ($idx < $dict_len) 245 while ($idx < $dict_len) 246 set var $c = $dict[$id 246 set var $c = $dict[$idx] 247 if ($c == '\0') 247 if ($c == '\0') 248 loop_break 248 loop_break 249 else 249 else 250 if ($c < ' ' | 250 if ($c < ' ' || $c >= 127 || $c == '\\') 251 printf 251 printf "\\x%02x", $c 252 else 252 else 253 printf 253 printf "%c", $c 254 end 254 end 255 end 255 end 256 set var $idx = $idx + 256 set var $idx = $idx + 1 257 end 257 end 258 printf "\n" 258 printf "\n" 259 end 259 end 260 260 261 set var $dict = &$info->dev_info.devic 261 set var $dict = &$info->dev_info.device[0] 262 set var $dict_len = sizeof($info->dev_ 262 set var $dict_len = sizeof($info->dev_info.device) 263 if ($dict[0] != '\0') 263 if ($dict[0] != '\0') 264 printf " DEVICE=" 264 printf " DEVICE=" 265 set var $idx = 0 265 set var $idx = 0 266 while ($idx < $dict_len) 266 while ($idx < $dict_len) 267 set var $c = $dict[$id 267 set var $c = $dict[$idx] 268 if ($c == '\0') 268 if ($c == '\0') 269 loop_break 269 loop_break 270 else 270 else 271 if ($c < ' ' | 271 if ($c < ' ' || $c >= 127 || $c == '\\') 272 printf 272 printf "\\x%02x", $c 273 else 273 else 274 printf 274 printf "%c", $c 275 end 275 end 276 end 276 end 277 set var $idx = $idx + 277 set var $idx = $idx + 1 278 end 278 end 279 printf "\n" 279 printf "\n" 280 end 280 end 281 end 281 end 282 document dump_record 282 document dump_record 283 Dump a single record. The first parame 283 Dump a single record. The first parameter is the descriptor, 284 the second parameter is the info, the 284 the second parameter is the info, the third parameter is 285 optional and specifies the previous re 285 optional and specifies the previous record's flags, used for 286 properly formatting continued lines. 286 properly formatting continued lines. 287 end 287 end 288 288 289 define dmesg 289 define dmesg 290 # definitions from kernel/printk/print 290 # definitions from kernel/printk/printk_ringbuffer.h 291 set var $desc_committed = 1 291 set var $desc_committed = 1 292 set var $desc_finalized = 2 292 set var $desc_finalized = 2 293 set var $desc_sv_bits = sizeof(long) * 293 set var $desc_sv_bits = sizeof(long) * 8 294 set var $desc_flags_shift = $desc_sv_b 294 set var $desc_flags_shift = $desc_sv_bits - 2 295 set var $desc_flags_mask = 3 << $desc_ 295 set var $desc_flags_mask = 3 << $desc_flags_shift 296 set var $id_mask = ~$desc_flags_mask 296 set var $id_mask = ~$desc_flags_mask 297 297 298 set var $desc_count = 1U << prb->desc_ 298 set var $desc_count = 1U << prb->desc_ring.count_bits 299 set var $prev_flags = 0 299 set var $prev_flags = 0 300 300 301 set var $id = prb->desc_ring.tail_id.c 301 set var $id = prb->desc_ring.tail_id.counter 302 set var $end_id = prb->desc_ring.head_ 302 set var $end_id = prb->desc_ring.head_id.counter 303 303 304 while (1) 304 while (1) 305 set var $desc = &prb->desc_rin 305 set var $desc = &prb->desc_ring.descs[$id % $desc_count] 306 set var $info = &prb->desc_rin 306 set var $info = &prb->desc_ring.infos[$id % $desc_count] 307 307 308 # skip non-committed record 308 # skip non-committed record 309 set var $state = 3 & ($desc->s 309 set var $state = 3 & ($desc->state_var.counter >> $desc_flags_shift) 310 if ($state == $desc_committed 310 if ($state == $desc_committed || $state == $desc_finalized) 311 dump_record $desc $inf 311 dump_record $desc $info $prev_flags 312 set var $prev_flags = 312 set var $prev_flags = $info->flags 313 end 313 end 314 314 >> 315 set var $id = ($id + 1) & $id_mask 315 if ($id == $end_id) 316 if ($id == $end_id) 316 loop_break 317 loop_break 317 end 318 end 318 set var $id = ($id + 1) & $id_ << 319 end 319 end 320 end 320 end 321 document dmesg 321 document dmesg 322 print the kernel ring buffer 322 print the kernel ring buffer 323 end 323 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.