mirror of
https://github.com/torvalds/linux.git
synced 2024-11-12 07:01:57 +00:00
a0c20deae9
Lots of little changes needed to be made to clean these up, remove the four byte pointer assumption and traverse the pid queue properly. Also consolidate the traceback code into a single function instead of having three copies of it. Link: http://lkml.kernel.org/r/1462926655-9390-1-git-send-email-minyard@acm.org Signed-off-by: Corey Minyard <cminyard@mvista.com> Acked-by: Baoquan He <bhe@redhat.com> Cc: Vivek Goyal <vgoyal@redhat.com> Cc: Haren Myneni <hbabu@us.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
194 lines
5.5 KiB
Plaintext
194 lines
5.5 KiB
Plaintext
#
|
|
# This file contains a few gdb macros (user defined commands) to extract
|
|
# useful information from kernel crashdump (kdump) like stack traces of
|
|
# all the processes or a particular process and trapinfo.
|
|
#
|
|
# These macros can be used by copying this file in .gdbinit (put in home
|
|
# directory or current directory) or by invoking gdb command with
|
|
# --command=<command-file-name> option
|
|
#
|
|
# Credits:
|
|
# Alexander Nyberg <alexn@telia.com>
|
|
# V Srivatsa <vatsa@in.ibm.com>
|
|
# Maneesh Soni <maneesh@in.ibm.com>
|
|
#
|
|
|
|
define bttnobp
|
|
set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
|
|
set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next)
|
|
set $init_t=&init_task
|
|
set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
|
|
set var $stacksize = sizeof(union thread_union)
|
|
while ($next_t != $init_t)
|
|
set $next_t=(struct task_struct *)$next_t
|
|
printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm
|
|
printf "===================\n"
|
|
set var $stackp = $next_t.thread.sp
|
|
set var $stack_top = ($stackp & ~($stacksize - 1)) + $stacksize
|
|
|
|
while ($stackp < $stack_top)
|
|
if (*($stackp) > _stext && *($stackp) < _sinittext)
|
|
info symbol *($stackp)
|
|
end
|
|
set $stackp += 4
|
|
end
|
|
set $next_th=(((char *)$next_t->thread_group.next) - $pid_off)
|
|
while ($next_th != $next_t)
|
|
set $next_th=(struct task_struct *)$next_th
|
|
printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm
|
|
printf "===================\n"
|
|
set var $stackp = $next_t.thread.sp
|
|
set var $stack_top = ($stackp & ~($stacksize - 1)) + stacksize
|
|
|
|
while ($stackp < $stack_top)
|
|
if (*($stackp) > _stext && *($stackp) < _sinittext)
|
|
info symbol *($stackp)
|
|
end
|
|
set $stackp += 4
|
|
end
|
|
set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)
|
|
end
|
|
set $next_t=(char *)($next_t->tasks.next) - $tasks_off
|
|
end
|
|
end
|
|
document bttnobp
|
|
dump all thread stack traces on a kernel compiled with !CONFIG_FRAME_POINTER
|
|
end
|
|
|
|
define btthreadstack
|
|
set var $pid_task = $arg0
|
|
|
|
printf "\npid %d; comm %s:\n", $pid_task.pid, $pid_task.comm
|
|
printf "task struct: "
|
|
print $pid_task
|
|
printf "===================\n"
|
|
set var $stackp = $pid_task.thread.sp
|
|
set var $stacksize = sizeof(union thread_union)
|
|
set var $stack_top = ($stackp & ~($stacksize - 1)) + $stacksize
|
|
set var $stack_bot = ($stackp & ~($stacksize - 1))
|
|
|
|
set $stackp = *((unsigned long *) $stackp)
|
|
while (($stackp < $stack_top) && ($stackp > $stack_bot))
|
|
set var $addr = *(((unsigned long *) $stackp) + 1)
|
|
info symbol $addr
|
|
set $stackp = *((unsigned long *) $stackp)
|
|
end
|
|
end
|
|
document btthreadstack
|
|
dump a thread stack using the given task structure pointer
|
|
end
|
|
|
|
|
|
define btt
|
|
set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
|
|
set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next)
|
|
set $init_t=&init_task
|
|
set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
|
|
while ($next_t != $init_t)
|
|
set $next_t=(struct task_struct *)$next_t
|
|
btthreadstack $next_t
|
|
|
|
set $next_th=(((char *)$next_t->thread_group.next) - $pid_off)
|
|
while ($next_th != $next_t)
|
|
set $next_th=(struct task_struct *)$next_th
|
|
btthreadstack $next_th
|
|
set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)
|
|
end
|
|
set $next_t=(char *)($next_t->tasks.next) - $tasks_off
|
|
end
|
|
end
|
|
document btt
|
|
dump all thread stack traces on a kernel compiled with CONFIG_FRAME_POINTER
|
|
end
|
|
|
|
define btpid
|
|
set var $pid = $arg0
|
|
set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
|
|
set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next)
|
|
set $init_t=&init_task
|
|
set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
|
|
set var $pid_task = 0
|
|
|
|
while ($next_t != $init_t)
|
|
set $next_t=(struct task_struct *)$next_t
|
|
|
|
if ($next_t.pid == $pid)
|
|
set $pid_task = $next_t
|
|
end
|
|
|
|
set $next_th=(((char *)$next_t->thread_group.next) - $pid_off)
|
|
while ($next_th != $next_t)
|
|
set $next_th=(struct task_struct *)$next_th
|
|
if ($next_th.pid == $pid)
|
|
set $pid_task = $next_th
|
|
end
|
|
set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)
|
|
end
|
|
set $next_t=(char *)($next_t->tasks.next) - $tasks_off
|
|
end
|
|
|
|
btthreadstack $pid_task
|
|
end
|
|
document btpid
|
|
backtrace of pid
|
|
end
|
|
|
|
|
|
define trapinfo
|
|
set var $pid = $arg0
|
|
set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
|
|
set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next)
|
|
set $init_t=&init_task
|
|
set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
|
|
set var $pid_task = 0
|
|
|
|
while ($next_t != $init_t)
|
|
set $next_t=(struct task_struct *)$next_t
|
|
|
|
if ($next_t.pid == $pid)
|
|
set $pid_task = $next_t
|
|
end
|
|
|
|
set $next_th=(((char *)$next_t->thread_group.next) - $pid_off)
|
|
while ($next_th != $next_t)
|
|
set $next_th=(struct task_struct *)$next_th
|
|
if ($next_th.pid == $pid)
|
|
set $pid_task = $next_th
|
|
end
|
|
set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)
|
|
end
|
|
set $next_t=(char *)($next_t->tasks.next) - $tasks_off
|
|
end
|
|
|
|
printf "Trapno %ld, cr2 0x%lx, error_code %ld\n", $pid_task.thread.trap_no, \
|
|
$pid_task.thread.cr2, $pid_task.thread.error_code
|
|
|
|
end
|
|
document trapinfo
|
|
Run info threads and lookup pid of thread #1
|
|
'trapinfo <pid>' will tell you by which trap & possibly
|
|
address the kernel panicked.
|
|
end
|
|
|
|
|
|
define dmesg
|
|
set $i = 0
|
|
set $end_idx = (log_end - 1) & (log_buf_len - 1)
|
|
|
|
while ($i < logged_chars)
|
|
set $idx = (log_end - 1 - logged_chars + $i) & (log_buf_len - 1)
|
|
|
|
if ($idx + 100 <= $end_idx) || \
|
|
($end_idx <= $idx && $idx + 100 < log_buf_len)
|
|
printf "%.100s", &log_buf[$idx]
|
|
set $i = $i + 100
|
|
else
|
|
printf "%c", log_buf[$idx]
|
|
set $i = $i + 1
|
|
end
|
|
end
|
|
end
|
|
document dmesg
|
|
print the kernel ring buffer
|
|
end
|