1330d4810SMauro Carvalho Chehab# 2330d4810SMauro Carvalho Chehab# This file contains a few gdb macros (user defined commands) to extract 3330d4810SMauro Carvalho Chehab# useful information from kernel crashdump (kdump) like stack traces of 4330d4810SMauro Carvalho Chehab# all the processes or a particular process and trapinfo. 5330d4810SMauro Carvalho Chehab# 6330d4810SMauro Carvalho Chehab# These macros can be used by copying this file in .gdbinit (put in home 7330d4810SMauro Carvalho Chehab# directory or current directory) or by invoking gdb command with 8330d4810SMauro Carvalho Chehab# --command=<command-file-name> option 9330d4810SMauro Carvalho Chehab# 10330d4810SMauro Carvalho Chehab# Credits: 11330d4810SMauro Carvalho Chehab# Alexander Nyberg <alexn@telia.com> 12330d4810SMauro Carvalho Chehab# V Srivatsa <vatsa@in.ibm.com> 13330d4810SMauro Carvalho Chehab# Maneesh Soni <maneesh@in.ibm.com> 14330d4810SMauro Carvalho Chehab# 15330d4810SMauro Carvalho Chehab 16330d4810SMauro Carvalho Chehabdefine bttnobp 17330d4810SMauro Carvalho Chehab set $tasks_off=((size_t)&((struct task_struct *)0)->tasks) 18330d4810SMauro Carvalho Chehab set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next) 19330d4810SMauro Carvalho Chehab set $init_t=&init_task 20330d4810SMauro Carvalho Chehab set $next_t=(((char *)($init_t->tasks).next) - $tasks_off) 21330d4810SMauro Carvalho Chehab set var $stacksize = sizeof(union thread_union) 22330d4810SMauro Carvalho Chehab while ($next_t != $init_t) 23330d4810SMauro Carvalho Chehab set $next_t=(struct task_struct *)$next_t 24330d4810SMauro Carvalho Chehab printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm 25330d4810SMauro Carvalho Chehab printf "===================\n" 26330d4810SMauro Carvalho Chehab set var $stackp = $next_t.thread.sp 27330d4810SMauro Carvalho Chehab set var $stack_top = ($stackp & ~($stacksize - 1)) + $stacksize 28330d4810SMauro Carvalho Chehab 29330d4810SMauro Carvalho Chehab while ($stackp < $stack_top) 30330d4810SMauro Carvalho Chehab if (*($stackp) > _stext && *($stackp) < _sinittext) 31330d4810SMauro Carvalho Chehab info symbol *($stackp) 32330d4810SMauro Carvalho Chehab end 33330d4810SMauro Carvalho Chehab set $stackp += 4 34330d4810SMauro Carvalho Chehab end 35330d4810SMauro Carvalho Chehab set $next_th=(((char *)$next_t->thread_group.next) - $pid_off) 36330d4810SMauro Carvalho Chehab while ($next_th != $next_t) 37330d4810SMauro Carvalho Chehab set $next_th=(struct task_struct *)$next_th 38330d4810SMauro Carvalho Chehab printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm 39330d4810SMauro Carvalho Chehab printf "===================\n" 40330d4810SMauro Carvalho Chehab set var $stackp = $next_t.thread.sp 41330d4810SMauro Carvalho Chehab set var $stack_top = ($stackp & ~($stacksize - 1)) + stacksize 42330d4810SMauro Carvalho Chehab 43330d4810SMauro Carvalho Chehab while ($stackp < $stack_top) 44330d4810SMauro Carvalho Chehab if (*($stackp) > _stext && *($stackp) < _sinittext) 45330d4810SMauro Carvalho Chehab info symbol *($stackp) 46330d4810SMauro Carvalho Chehab end 47330d4810SMauro Carvalho Chehab set $stackp += 4 48330d4810SMauro Carvalho Chehab end 49330d4810SMauro Carvalho Chehab set $next_th=(((char *)$next_th->thread_group.next) - $pid_off) 50330d4810SMauro Carvalho Chehab end 51330d4810SMauro Carvalho Chehab set $next_t=(char *)($next_t->tasks.next) - $tasks_off 52330d4810SMauro Carvalho Chehab end 53330d4810SMauro Carvalho Chehabend 54330d4810SMauro Carvalho Chehabdocument bttnobp 55330d4810SMauro Carvalho Chehab dump all thread stack traces on a kernel compiled with !CONFIG_FRAME_POINTER 56330d4810SMauro Carvalho Chehabend 57330d4810SMauro Carvalho Chehab 58330d4810SMauro Carvalho Chehabdefine btthreadstack 59330d4810SMauro Carvalho Chehab set var $pid_task = $arg0 60330d4810SMauro Carvalho Chehab 61330d4810SMauro Carvalho Chehab printf "\npid %d; comm %s:\n", $pid_task.pid, $pid_task.comm 62330d4810SMauro Carvalho Chehab printf "task struct: " 63330d4810SMauro Carvalho Chehab print $pid_task 64330d4810SMauro Carvalho Chehab printf "===================\n" 65330d4810SMauro Carvalho Chehab set var $stackp = $pid_task.thread.sp 66330d4810SMauro Carvalho Chehab set var $stacksize = sizeof(union thread_union) 67330d4810SMauro Carvalho Chehab set var $stack_top = ($stackp & ~($stacksize - 1)) + $stacksize 68330d4810SMauro Carvalho Chehab set var $stack_bot = ($stackp & ~($stacksize - 1)) 69330d4810SMauro Carvalho Chehab 70330d4810SMauro Carvalho Chehab set $stackp = *((unsigned long *) $stackp) 71330d4810SMauro Carvalho Chehab while (($stackp < $stack_top) && ($stackp > $stack_bot)) 72330d4810SMauro Carvalho Chehab set var $addr = *(((unsigned long *) $stackp) + 1) 73330d4810SMauro Carvalho Chehab info symbol $addr 74330d4810SMauro Carvalho Chehab set $stackp = *((unsigned long *) $stackp) 75330d4810SMauro Carvalho Chehab end 76330d4810SMauro Carvalho Chehabend 77330d4810SMauro Carvalho Chehabdocument btthreadstack 78330d4810SMauro Carvalho Chehab dump a thread stack using the given task structure pointer 79330d4810SMauro Carvalho Chehabend 80330d4810SMauro Carvalho Chehab 81330d4810SMauro Carvalho Chehab 82330d4810SMauro Carvalho Chehabdefine btt 83330d4810SMauro Carvalho Chehab set $tasks_off=((size_t)&((struct task_struct *)0)->tasks) 84330d4810SMauro Carvalho Chehab set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next) 85330d4810SMauro Carvalho Chehab set $init_t=&init_task 86330d4810SMauro Carvalho Chehab set $next_t=(((char *)($init_t->tasks).next) - $tasks_off) 87330d4810SMauro Carvalho Chehab while ($next_t != $init_t) 88330d4810SMauro Carvalho Chehab set $next_t=(struct task_struct *)$next_t 89330d4810SMauro Carvalho Chehab btthreadstack $next_t 90330d4810SMauro Carvalho Chehab 91330d4810SMauro Carvalho Chehab set $next_th=(((char *)$next_t->thread_group.next) - $pid_off) 92330d4810SMauro Carvalho Chehab while ($next_th != $next_t) 93330d4810SMauro Carvalho Chehab set $next_th=(struct task_struct *)$next_th 94330d4810SMauro Carvalho Chehab btthreadstack $next_th 95330d4810SMauro Carvalho Chehab set $next_th=(((char *)$next_th->thread_group.next) - $pid_off) 96330d4810SMauro Carvalho Chehab end 97330d4810SMauro Carvalho Chehab set $next_t=(char *)($next_t->tasks.next) - $tasks_off 98330d4810SMauro Carvalho Chehab end 99330d4810SMauro Carvalho Chehabend 100330d4810SMauro Carvalho Chehabdocument btt 101330d4810SMauro Carvalho Chehab dump all thread stack traces on a kernel compiled with CONFIG_FRAME_POINTER 102330d4810SMauro Carvalho Chehabend 103330d4810SMauro Carvalho Chehab 104330d4810SMauro Carvalho Chehabdefine btpid 105330d4810SMauro Carvalho Chehab set var $pid = $arg0 106330d4810SMauro Carvalho Chehab set $tasks_off=((size_t)&((struct task_struct *)0)->tasks) 107330d4810SMauro Carvalho Chehab set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next) 108330d4810SMauro Carvalho Chehab set $init_t=&init_task 109330d4810SMauro Carvalho Chehab set $next_t=(((char *)($init_t->tasks).next) - $tasks_off) 110330d4810SMauro Carvalho Chehab set var $pid_task = 0 111330d4810SMauro Carvalho Chehab 112330d4810SMauro Carvalho Chehab while ($next_t != $init_t) 113330d4810SMauro Carvalho Chehab set $next_t=(struct task_struct *)$next_t 114330d4810SMauro Carvalho Chehab 115330d4810SMauro Carvalho Chehab if ($next_t.pid == $pid) 116330d4810SMauro Carvalho Chehab set $pid_task = $next_t 117330d4810SMauro Carvalho Chehab end 118330d4810SMauro Carvalho Chehab 119330d4810SMauro Carvalho Chehab set $next_th=(((char *)$next_t->thread_group.next) - $pid_off) 120330d4810SMauro Carvalho Chehab while ($next_th != $next_t) 121330d4810SMauro Carvalho Chehab set $next_th=(struct task_struct *)$next_th 122330d4810SMauro Carvalho Chehab if ($next_th.pid == $pid) 123330d4810SMauro Carvalho Chehab set $pid_task = $next_th 124330d4810SMauro Carvalho Chehab end 125330d4810SMauro Carvalho Chehab set $next_th=(((char *)$next_th->thread_group.next) - $pid_off) 126330d4810SMauro Carvalho Chehab end 127330d4810SMauro Carvalho Chehab set $next_t=(char *)($next_t->tasks.next) - $tasks_off 128330d4810SMauro Carvalho Chehab end 129330d4810SMauro Carvalho Chehab 130330d4810SMauro Carvalho Chehab btthreadstack $pid_task 131330d4810SMauro Carvalho Chehabend 132330d4810SMauro Carvalho Chehabdocument btpid 133330d4810SMauro Carvalho Chehab backtrace of pid 134330d4810SMauro Carvalho Chehabend 135330d4810SMauro Carvalho Chehab 136330d4810SMauro Carvalho Chehab 137330d4810SMauro Carvalho Chehabdefine trapinfo 138330d4810SMauro Carvalho Chehab set var $pid = $arg0 139330d4810SMauro Carvalho Chehab set $tasks_off=((size_t)&((struct task_struct *)0)->tasks) 140330d4810SMauro Carvalho Chehab set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next) 141330d4810SMauro Carvalho Chehab set $init_t=&init_task 142330d4810SMauro Carvalho Chehab set $next_t=(((char *)($init_t->tasks).next) - $tasks_off) 143330d4810SMauro Carvalho Chehab set var $pid_task = 0 144330d4810SMauro Carvalho Chehab 145330d4810SMauro Carvalho Chehab while ($next_t != $init_t) 146330d4810SMauro Carvalho Chehab set $next_t=(struct task_struct *)$next_t 147330d4810SMauro Carvalho Chehab 148330d4810SMauro Carvalho Chehab if ($next_t.pid == $pid) 149330d4810SMauro Carvalho Chehab set $pid_task = $next_t 150330d4810SMauro Carvalho Chehab end 151330d4810SMauro Carvalho Chehab 152330d4810SMauro Carvalho Chehab set $next_th=(((char *)$next_t->thread_group.next) - $pid_off) 153330d4810SMauro Carvalho Chehab while ($next_th != $next_t) 154330d4810SMauro Carvalho Chehab set $next_th=(struct task_struct *)$next_th 155330d4810SMauro Carvalho Chehab if ($next_th.pid == $pid) 156330d4810SMauro Carvalho Chehab set $pid_task = $next_th 157330d4810SMauro Carvalho Chehab end 158330d4810SMauro Carvalho Chehab set $next_th=(((char *)$next_th->thread_group.next) - $pid_off) 159330d4810SMauro Carvalho Chehab end 160330d4810SMauro Carvalho Chehab set $next_t=(char *)($next_t->tasks.next) - $tasks_off 161330d4810SMauro Carvalho Chehab end 162330d4810SMauro Carvalho Chehab 163330d4810SMauro Carvalho Chehab printf "Trapno %ld, cr2 0x%lx, error_code %ld\n", $pid_task.thread.trap_no, \ 164330d4810SMauro Carvalho Chehab $pid_task.thread.cr2, $pid_task.thread.error_code 165330d4810SMauro Carvalho Chehab 166330d4810SMauro Carvalho Chehabend 167330d4810SMauro Carvalho Chehabdocument trapinfo 168330d4810SMauro Carvalho Chehab Run info threads and lookup pid of thread #1 169330d4810SMauro Carvalho Chehab 'trapinfo <pid>' will tell you by which trap & possibly 170330d4810SMauro Carvalho Chehab address the kernel panicked. 171330d4810SMauro Carvalho Chehabend 172330d4810SMauro Carvalho Chehab 173e6076831SJohn Ognessdefine dump_record 174e6076831SJohn Ogness set var $desc = $arg0 17574caba7fSJohn Ogness set var $info = $arg1 17674caba7fSJohn Ogness if ($argc > 2) 17774caba7fSJohn Ogness set var $prev_flags = $arg2 178330d4810SMauro Carvalho Chehab else 179e6076831SJohn Ogness set var $prev_flags = 0 180330d4810SMauro Carvalho Chehab end 181330d4810SMauro Carvalho Chehab 182e6076831SJohn Ogness set var $prefix = 1 183e6076831SJohn Ogness set var $newline = 1 184e6076831SJohn Ogness 185e6076831SJohn Ogness set var $begin = $desc->text_blk_lpos.begin % (1U << prb->text_data_ring.size_bits) 186e6076831SJohn Ogness set var $next = $desc->text_blk_lpos.next % (1U << prb->text_data_ring.size_bits) 187e6076831SJohn Ogness 188e6076831SJohn Ogness # handle data-less record 189e6076831SJohn Ogness if ($begin & 1) 190e6076831SJohn Ogness set var $text_len = 0 191e6076831SJohn Ogness set var $log = "" 192e6076831SJohn Ogness else 193e6076831SJohn Ogness # handle wrapping data block 194e6076831SJohn Ogness if ($begin > $next) 195e6076831SJohn Ogness set var $begin = 0 196e6076831SJohn Ogness end 197e6076831SJohn Ogness 198e6076831SJohn Ogness # skip over descriptor id 199e6076831SJohn Ogness set var $begin = $begin + sizeof(long) 200e6076831SJohn Ogness 201e6076831SJohn Ogness # handle truncated message 202e6076831SJohn Ogness if ($next - $begin < $info->text_len) 203e6076831SJohn Ogness set var $text_len = $next - $begin 204e6076831SJohn Ogness else 205e6076831SJohn Ogness set var $text_len = $info->text_len 206e6076831SJohn Ogness end 207e6076831SJohn Ogness 208e6076831SJohn Ogness set var $log = &prb->text_data_ring.data[$begin] 209e6076831SJohn Ogness end 210e6076831SJohn Ogness 211e6076831SJohn Ogness # prev & LOG_CONT && !(info->flags & LOG_PREIX) 212e6076831SJohn Ogness if (($prev_flags & 8) && !($info->flags & 4)) 213e6076831SJohn Ogness set var $prefix = 0 214e6076831SJohn Ogness end 215e6076831SJohn Ogness 216e6076831SJohn Ogness # info->flags & LOG_CONT 217e6076831SJohn Ogness if ($info->flags & 8) 218330d4810SMauro Carvalho Chehab # (prev & LOG_CONT && !(prev & LOG_NEWLINE)) 219330d4810SMauro Carvalho Chehab if (($prev_flags & 8) && !($prev_flags & 2)) 220e6076831SJohn Ogness set var $prefix = 0 221330d4810SMauro Carvalho Chehab end 222e6076831SJohn Ogness # (!(info->flags & LOG_NEWLINE)) 223e6076831SJohn Ogness if (!($info->flags & 2)) 224e6076831SJohn Ogness set var $newline = 0 225330d4810SMauro Carvalho Chehab end 226330d4810SMauro Carvalho Chehab end 227330d4810SMauro Carvalho Chehab 228330d4810SMauro Carvalho Chehab if ($prefix) 229e6076831SJohn Ogness printf "[%5lu.%06lu] ", $info->ts_nsec / 1000000000, $info->ts_nsec % 1000000000 230330d4810SMauro Carvalho Chehab end 231e6076831SJohn Ogness if ($text_len) 232e6076831SJohn Ogness eval "printf \"%%%d.%ds\", $log", $text_len, $text_len 233330d4810SMauro Carvalho Chehab end 234330d4810SMauro Carvalho Chehab if ($newline) 235330d4810SMauro Carvalho Chehab printf "\n" 236330d4810SMauro Carvalho Chehab end 237e6076831SJohn Ogness 238e6076831SJohn Ogness # handle dictionary data 239e6076831SJohn Ogness 24074caba7fSJohn Ogness set var $dict = &$info->dev_info.subsystem[0] 24174caba7fSJohn Ogness set var $dict_len = sizeof($info->dev_info.subsystem) 24274caba7fSJohn Ogness if ($dict[0] != '\0') 24374caba7fSJohn Ogness printf " SUBSYSTEM=" 244e6076831SJohn Ogness set var $idx = 0 245e6076831SJohn Ogness while ($idx < $dict_len) 246e6076831SJohn Ogness set var $c = $dict[$idx] 247330d4810SMauro Carvalho Chehab if ($c == '\0') 24874caba7fSJohn Ogness loop_break 24974caba7fSJohn Ogness else 25074caba7fSJohn Ogness if ($c < ' ' || $c >= 127 || $c == '\\') 25174caba7fSJohn Ogness printf "\\x%02x", $c 25274caba7fSJohn Ogness else 25374caba7fSJohn Ogness printf "%c", $c 25474caba7fSJohn Ogness end 25574caba7fSJohn Ogness end 25674caba7fSJohn Ogness set var $idx = $idx + 1 25774caba7fSJohn Ogness end 258330d4810SMauro Carvalho Chehab printf "\n" 25974caba7fSJohn Ogness end 26074caba7fSJohn Ogness 26174caba7fSJohn Ogness set var $dict = &$info->dev_info.device[0] 26274caba7fSJohn Ogness set var $dict_len = sizeof($info->dev_info.device) 26374caba7fSJohn Ogness if ($dict[0] != '\0') 26474caba7fSJohn Ogness printf " DEVICE=" 26574caba7fSJohn Ogness set var $idx = 0 26674caba7fSJohn Ogness while ($idx < $dict_len) 26774caba7fSJohn Ogness set var $c = $dict[$idx] 26874caba7fSJohn Ogness if ($c == '\0') 26974caba7fSJohn Ogness loop_break 270330d4810SMauro Carvalho Chehab else 271330d4810SMauro Carvalho Chehab if ($c < ' ' || $c >= 127 || $c == '\\') 272330d4810SMauro Carvalho Chehab printf "\\x%02x", $c 273330d4810SMauro Carvalho Chehab else 274330d4810SMauro Carvalho Chehab printf "%c", $c 275330d4810SMauro Carvalho Chehab end 276330d4810SMauro Carvalho Chehab end 277e6076831SJohn Ogness set var $idx = $idx + 1 278330d4810SMauro Carvalho Chehab end 279330d4810SMauro Carvalho Chehab printf "\n" 280330d4810SMauro Carvalho Chehab end 281330d4810SMauro Carvalho Chehabend 282e6076831SJohn Ognessdocument dump_record 28374caba7fSJohn Ogness Dump a single record. The first parameter is the descriptor, 28474caba7fSJohn Ogness the second parameter is the info, the third parameter is 28574caba7fSJohn Ogness optional and specifies the previous record's flags, used for 28674caba7fSJohn Ogness properly formatting continued lines. 287330d4810SMauro Carvalho Chehabend 288330d4810SMauro Carvalho Chehab 289330d4810SMauro Carvalho Chehabdefine dmesg 29010dcb06dSJohn Ogness # definitions from kernel/printk/printk_ringbuffer.h 29110dcb06dSJohn Ogness set var $desc_committed = 1 2924cfc7258SJohn Ogness set var $desc_finalized = 2 29310dcb06dSJohn Ogness set var $desc_sv_bits = sizeof(long) * 8 29410dcb06dSJohn Ogness set var $desc_flags_shift = $desc_sv_bits - 2 29510dcb06dSJohn Ogness set var $desc_flags_mask = 3 << $desc_flags_shift 29610dcb06dSJohn Ogness set var $id_mask = ~$desc_flags_mask 297e6076831SJohn Ogness 298e6076831SJohn Ogness set var $desc_count = 1U << prb->desc_ring.count_bits 299e6076831SJohn Ogness set var $prev_flags = 0 300e6076831SJohn Ogness 301e6076831SJohn Ogness set var $id = prb->desc_ring.tail_id.counter 302e6076831SJohn Ogness set var $end_id = prb->desc_ring.head_id.counter 303330d4810SMauro Carvalho Chehab 304330d4810SMauro Carvalho Chehab while (1) 305e6076831SJohn Ogness set var $desc = &prb->desc_ring.descs[$id % $desc_count] 30674caba7fSJohn Ogness set var $info = &prb->desc_ring.infos[$id % $desc_count] 307e6076831SJohn Ogness 308e6076831SJohn Ogness # skip non-committed record 30910dcb06dSJohn Ogness set var $state = 3 & ($desc->state_var.counter >> $desc_flags_shift) 3104cfc7258SJohn Ogness if ($state == $desc_committed || $state == $desc_finalized) 31174caba7fSJohn Ogness dump_record $desc $info $prev_flags 31274caba7fSJohn Ogness set var $prev_flags = $info->flags 313330d4810SMauro Carvalho Chehab end 314e6076831SJohn Ogness 315e6076831SJohn Ogness if ($id == $end_id) 316330d4810SMauro Carvalho Chehab loop_break 317330d4810SMauro Carvalho Chehab end 318*f2e4cca2SJohn Ogness set var $id = ($id + 1) & $id_mask 319330d4810SMauro Carvalho Chehab end 320330d4810SMauro Carvalho Chehabend 321330d4810SMauro Carvalho Chehabdocument dmesg 322330d4810SMauro Carvalho Chehab print the kernel ring buffer 323330d4810SMauro Carvalho Chehabend 324