Path: blob/master/Documentation/admin-guide/kdump/gdbmacros.txt
26299 views
#1# This file contains a few gdb macros (user defined commands) to extract2# useful information from kernel crashdump (kdump) like stack traces of3# all the processes or a particular process and trapinfo.4#5# These macros can be used by copying this file in .gdbinit (put in home6# directory or current directory) or by invoking gdb command with7# --command=<command-file-name> option8#9# Credits:10# Alexander Nyberg <[email protected]>11# V Srivatsa <[email protected]>12# Maneesh Soni <[email protected]>13#1415define bttnobp16set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)17set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next)18set $init_t=&init_task19set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)20set var $stacksize = sizeof(union thread_union)21while ($next_t != $init_t)22set $next_t=(struct task_struct *)$next_t23printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm24printf "===================\n"25set var $stackp = $next_t.thread.sp26set var $stack_top = ($stackp & ~($stacksize - 1)) + $stacksize2728while ($stackp < $stack_top)29if (*($stackp) > _stext && *($stackp) < _sinittext)30info symbol *($stackp)31end32set $stackp += 433end34set $next_th=(((char *)$next_t->thread_group.next) - $pid_off)35while ($next_th != $next_t)36set $next_th=(struct task_struct *)$next_th37printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm38printf "===================\n"39set var $stackp = $next_t.thread.sp40set var $stack_top = ($stackp & ~($stacksize - 1)) + stacksize4142while ($stackp < $stack_top)43if (*($stackp) > _stext && *($stackp) < _sinittext)44info symbol *($stackp)45end46set $stackp += 447end48set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)49end50set $next_t=(char *)($next_t->tasks.next) - $tasks_off51end52end53document bttnobp54dump all thread stack traces on a kernel compiled with !CONFIG_FRAME_POINTER55end5657define btthreadstack58set var $pid_task = $arg05960printf "\npid %d; comm %s:\n", $pid_task.pid, $pid_task.comm61printf "task struct: "62print $pid_task63printf "===================\n"64set var $stackp = $pid_task.thread.sp65set var $stacksize = sizeof(union thread_union)66set var $stack_top = ($stackp & ~($stacksize - 1)) + $stacksize67set var $stack_bot = ($stackp & ~($stacksize - 1))6869set $stackp = *((unsigned long *) $stackp)70while (($stackp < $stack_top) && ($stackp > $stack_bot))71set var $addr = *(((unsigned long *) $stackp) + 1)72info symbol $addr73set $stackp = *((unsigned long *) $stackp)74end75end76document btthreadstack77dump a thread stack using the given task structure pointer78end798081define btt82set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)83set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next)84set $init_t=&init_task85set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)86while ($next_t != $init_t)87set $next_t=(struct task_struct *)$next_t88btthreadstack $next_t8990set $next_th=(((char *)$next_t->thread_group.next) - $pid_off)91while ($next_th != $next_t)92set $next_th=(struct task_struct *)$next_th93btthreadstack $next_th94set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)95end96set $next_t=(char *)($next_t->tasks.next) - $tasks_off97end98end99document btt100dump all thread stack traces on a kernel compiled with CONFIG_FRAME_POINTER101end102103define btpid104set var $pid = $arg0105set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)106set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next)107set $init_t=&init_task108set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)109set var $pid_task = 0110111while ($next_t != $init_t)112set $next_t=(struct task_struct *)$next_t113114if ($next_t.pid == $pid)115set $pid_task = $next_t116end117118set $next_th=(((char *)$next_t->thread_group.next) - $pid_off)119while ($next_th != $next_t)120set $next_th=(struct task_struct *)$next_th121if ($next_th.pid == $pid)122set $pid_task = $next_th123end124set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)125end126set $next_t=(char *)($next_t->tasks.next) - $tasks_off127end128129btthreadstack $pid_task130end131document btpid132backtrace of pid133end134135136define trapinfo137set var $pid = $arg0138set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)139set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next)140set $init_t=&init_task141set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)142set var $pid_task = 0143144while ($next_t != $init_t)145set $next_t=(struct task_struct *)$next_t146147if ($next_t.pid == $pid)148set $pid_task = $next_t149end150151set $next_th=(((char *)$next_t->thread_group.next) - $pid_off)152while ($next_th != $next_t)153set $next_th=(struct task_struct *)$next_th154if ($next_th.pid == $pid)155set $pid_task = $next_th156end157set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)158end159set $next_t=(char *)($next_t->tasks.next) - $tasks_off160end161162printf "Trapno %ld, cr2 0x%lx, error_code %ld\n", $pid_task.thread.trap_no, \163$pid_task.thread.cr2, $pid_task.thread.error_code164165end166document trapinfo167Run info threads and lookup pid of thread #1168'trapinfo <pid>' will tell you by which trap & possibly169address the kernel panicked.170end171172define dump_record173set var $desc = $arg0174set var $info = $arg1175if ($argc > 2)176set var $prev_flags = $arg2177else178set var $prev_flags = 0179end180181set var $prefix = 1182set var $newline = 1183184set var $begin = $desc->text_blk_lpos.begin % (1U << prb->text_data_ring.size_bits)185set var $next = $desc->text_blk_lpos.next % (1U << prb->text_data_ring.size_bits)186187# handle data-less record188if ($begin & 1)189set var $text_len = 0190set var $log = ""191else192# handle wrapping data block193if ($begin > $next)194set var $begin = 0195end196197# skip over descriptor id198set var $begin = $begin + sizeof(long)199200# handle truncated message201if ($next - $begin < $info->text_len)202set var $text_len = $next - $begin203else204set var $text_len = $info->text_len205end206207set var $log = &prb->text_data_ring.data[$begin]208end209210# prev & LOG_CONT && !(info->flags & LOG_PREIX)211if (($prev_flags & 8) && !($info->flags & 4))212set var $prefix = 0213end214215# info->flags & LOG_CONT216if ($info->flags & 8)217# (prev & LOG_CONT && !(prev & LOG_NEWLINE))218if (($prev_flags & 8) && !($prev_flags & 2))219set var $prefix = 0220end221# (!(info->flags & LOG_NEWLINE))222if (!($info->flags & 2))223set var $newline = 0224end225end226227if ($prefix)228printf "[%5lu.%06lu] ", $info->ts_nsec / 1000000000, $info->ts_nsec % 1000000000229end230if ($text_len)231eval "printf \"%%%d.%ds\", $log", $text_len, $text_len232end233if ($newline)234printf "\n"235end236237# handle dictionary data238239set var $dict = &$info->dev_info.subsystem[0]240set var $dict_len = sizeof($info->dev_info.subsystem)241if ($dict[0] != '\0')242printf " SUBSYSTEM="243set var $idx = 0244while ($idx < $dict_len)245set var $c = $dict[$idx]246if ($c == '\0')247loop_break248else249if ($c < ' ' || $c >= 127 || $c == '\\')250printf "\\x%02x", $c251else252printf "%c", $c253end254end255set var $idx = $idx + 1256end257printf "\n"258end259260set var $dict = &$info->dev_info.device[0]261set var $dict_len = sizeof($info->dev_info.device)262if ($dict[0] != '\0')263printf " DEVICE="264set var $idx = 0265while ($idx < $dict_len)266set var $c = $dict[$idx]267if ($c == '\0')268loop_break269else270if ($c < ' ' || $c >= 127 || $c == '\\')271printf "\\x%02x", $c272else273printf "%c", $c274end275end276set var $idx = $idx + 1277end278printf "\n"279end280end281document dump_record282Dump a single record. The first parameter is the descriptor,283the second parameter is the info, the third parameter is284optional and specifies the previous record's flags, used for285properly formatting continued lines.286end287288define dmesg289# definitions from kernel/printk/printk_ringbuffer.h290set var $desc_committed = 1291set var $desc_finalized = 2292set var $desc_sv_bits = sizeof(long) * 8293set var $desc_flags_shift = $desc_sv_bits - 2294set var $desc_flags_mask = 3 << $desc_flags_shift295set var $id_mask = ~$desc_flags_mask296297set var $desc_count = 1U << prb->desc_ring.count_bits298set var $prev_flags = 0299300set var $id = prb->desc_ring.tail_id.counter301set var $end_id = prb->desc_ring.head_id.counter302303while (1)304set var $desc = &prb->desc_ring.descs[$id % $desc_count]305set var $info = &prb->desc_ring.infos[$id % $desc_count]306307# skip non-committed record308set var $state = 3 & ($desc->state_var.counter >> $desc_flags_shift)309if ($state == $desc_committed || $state == $desc_finalized)310dump_record $desc $info $prev_flags311set var $prev_flags = $info->flags312end313314if ($id == $end_id)315loop_break316end317set var $id = ($id + 1) & $id_mask318end319end320document dmesg321print the kernel ring buffer322end323324325