Kernel-3.10.0-957.el7_gdbmacros

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= 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)->pids[1].pid_list.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
printf “\npid %d; comm %s:\n”, $next_t.pid, $next_t.comm
printf “===================\n”
set var $stackp = $next_t.thread.esp
set var $stack_top = ($stackp & ~4095) + 4096

    while ($stackp < $stack_top)
        if (*($stackp) > _stext && *($stackp) < _sinittext)
            info symbol *($stackp)
        end
        set $stackp += 4
    end
    set $next_th=(((char *)$next_t->pids[1].pid_list.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.esp
        set var $stack_top = ($stackp & ~4095) + 4096

        while ($stackp < $stack_top)
            if (*($stackp) > _stext && *($stackp) < _sinittext)
                info symbol *($stackp)
            end
            set $stackp += 4
        end
        set $next_th=(((char *)$next_th->pids[1].pid_list.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 btt
set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
set $pid_off=((size_t)&((struct task_struct *)0)->pids[1].pid_list.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
printf “\npid %d; comm %s:\n”, $next_t.pid, $next_t.comm
printf “===================\n”
set var $stackp = $next_t.thread.esp
set var $stack_top = ($stackp & ~4095) + 4096
set var $stack_bot = ($stackp & ~4095)

    set $stackp = *($stackp)
    while (($stackp < $stack_top) && ($stackp > $stack_bot))
        set var $addr = *($stackp + 4)
        info symbol $addr
        set $stackp = *($stackp)
    end

    set $next_th=(((char *)$next_t->pids[1].pid_list.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.esp
        set var $stack_top = ($stackp & ~4095) + 4096
        set var $stack_bot = ($stackp & ~4095)

        set $stackp = *($stackp)
        while (($stackp < $stack_top) && ($stackp > $stack_bot))
            set var $addr = *($stackp + 4)
            info symbol $addr
            set $stackp = *($stackp)
        end
        set $next_th=(((char *)$next_th->pids[1].pid_list.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)->pids[1].pid_list.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->pids[1].pid_list.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->pids[1].pid_list.next) - $pid_off)
    end
    set $next_t=(char *)($next_t->tasks.next) - $tasks_off
end

printf "\npid %d; comm %s:\n", $pid_task.pid, $pid_task.comm
printf "===================\n"
set var $stackp = $pid_task.thread.esp
set var $stack_top = ($stackp & ~4095) + 4096
set var $stack_bot = ($stackp & ~4095)

set $stackp = *($stackp)
while (($stackp < $stack_top) && ($stackp > $stack_bot))
    set var $addr = *($stackp + 4)
    info symbol $addr
    set $stackp = *($stackp)
end

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)->pids[1].pid_list.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->pids[1].pid_list.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->pids[1].pid_list.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 ‘ 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