Commit 26681eb3 authored by Stephen Boyd's avatar Stephen Boyd Committed by Linus Torvalds

scripts/decode_stacktrace.sh: support debuginfod

Now that stacktraces contain the build ID information we can update this
script to use debuginfod-find to locate the debuginfo for the vmlinux and
modules automatically.  This can replace the existing code that requires
specifying a path to vmlinux or tries to find the vmlinux and modules
automatically by using the release number.  Work it into the script as a
fallback option if the vmlinux isn't specified on the commandline.

Link: https://lkml.kernel.org/r/20210511003845.2429846-9-swboyd@chromium.orgSigned-off-by: default avatarStephen Boyd <swboyd@chromium.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Jessica Yu <jeyu@kernel.org>
Cc: Evan Green <evgreen@chromium.org>
Cc: Hsin-Yi Wang <hsinyi@chromium.org>
Cc: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>
Cc: Sasha Levin <sashal@kernel.org>
Cc: Petr Mladek <pmladek@suse.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Baoquan He <bhe@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Dave Young <dyoung@redhat.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Cc: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vivek Goyal <vgoyal@redhat.com>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 9ef8af2a
...@@ -3,11 +3,10 @@ ...@@ -3,11 +3,10 @@
# (c) 2014, Sasha Levin <sasha.levin@oracle.com> # (c) 2014, Sasha Levin <sasha.levin@oracle.com>
#set -x #set -x
if [[ $# < 1 ]]; then usage() {
echo "Usage:" echo "Usage:"
echo " $0 -r <release> | <vmlinux> [base path] [modules path]" echo " $0 -r <release> | <vmlinux> [base path] [modules path]"
exit 1 }
fi
if [[ $1 == "-r" ]] ; then if [[ $1 == "-r" ]] ; then
vmlinux="" vmlinux=""
...@@ -24,6 +23,7 @@ if [[ $1 == "-r" ]] ; then ...@@ -24,6 +23,7 @@ if [[ $1 == "-r" ]] ; then
if [[ $vmlinux == "" ]] ; then if [[ $vmlinux == "" ]] ; then
echo "ERROR! vmlinux image for release $release is not found" >&2 echo "ERROR! vmlinux image for release $release is not found" >&2
usage
exit 2 exit 2
fi fi
else else
...@@ -31,12 +31,35 @@ else ...@@ -31,12 +31,35 @@ else
basepath=${2-auto} basepath=${2-auto}
modpath=$3 modpath=$3
release="" release=""
debuginfod=
# Can we use debuginfod-find?
if type debuginfod-find >/dev/null 2>&1 ; then
debuginfod=${1-only}
fi
if [[ $vmlinux == "" && -z $debuginfod ]] ; then
echo "ERROR! vmlinux image must be specified" >&2
usage
exit 1
fi
fi fi
declare -A cache declare -A cache
declare -A modcache declare -A modcache
find_module() { find_module() {
if [[ -n $debuginfod ]] ; then
if [[ -n $modbuildid ]] ; then
debuginfod-find debuginfo $modbuildid && return
fi
# Only using debuginfod so don't try to find vmlinux module path
if [[ $debuginfod == "only" ]] ; then
return
fi
fi
if [[ "$modpath" != "" ]] ; then if [[ "$modpath" != "" ]] ; then
for fn in $(find "$modpath" -name "${module//_/[-_]}.ko*") ; do for fn in $(find "$modpath" -name "${module//_/[-_]}.ko*") ; do
if readelf -WS "$fn" | grep -qwF .debug_line ; then if readelf -WS "$fn" | grep -qwF .debug_line ; then
...@@ -150,6 +173,27 @@ parse_symbol() { ...@@ -150,6 +173,27 @@ parse_symbol() {
symbol="$segment$name ($code)" symbol="$segment$name ($code)"
} }
debuginfod_get_vmlinux() {
local vmlinux_buildid=${1##* }
if [[ $vmlinux != "" ]]; then
return
fi
if [[ $vmlinux_buildid =~ ^[0-9a-f]+ ]]; then
vmlinux=$(debuginfod-find debuginfo $vmlinux_buildid)
if [[ $? -ne 0 ]] ; then
echo "ERROR! vmlinux image not found via debuginfod-find" >&2
usage
exit 2
fi
return
fi
echo "ERROR! Build ID for vmlinux not found. Try passing -r or specifying vmlinux" >&2
usage
exit 2
}
decode_code() { decode_code() {
local scripts=`dirname "${BASH_SOURCE[0]}"` local scripts=`dirname "${BASH_SOURCE[0]}"`
...@@ -157,6 +201,14 @@ decode_code() { ...@@ -157,6 +201,14 @@ decode_code() {
} }
handle_line() { handle_line() {
if [[ $basepath == "auto" && $vmlinux != "" ]] ; then
module=""
symbol="kernel_init+0x0/0x0"
parse_symbol
basepath=${symbol#kernel_init (}
basepath=${basepath%/init/main.c:*)}
fi
local words local words
# Tokenize # Tokenize
...@@ -182,16 +234,28 @@ handle_line() { ...@@ -182,16 +234,28 @@ handle_line() {
fi fi
done done
if [[ ${words[$last]} =~ ^[0-9a-f]+\] ]]; then
words[$last-1]="${words[$last-1]} ${words[$last]}"
unset words[$last]
last=$(( $last - 1 ))
fi
if [[ ${words[$last]} =~ \[([^]]+)\] ]]; then if [[ ${words[$last]} =~ \[([^]]+)\] ]]; then
module=${words[$last]} module=${words[$last]}
module=${module#\[} module=${module#\[}
module=${module%\]} module=${module%\]}
modbuildid=${module#* }
module=${module% *}
if [[ $modbuildid == $module ]]; then
modbuildid=
fi
symbol=${words[$last-1]} symbol=${words[$last-1]}
unset words[$last-1] unset words[$last-1]
else else
# The symbol is the last element, process it # The symbol is the last element, process it
symbol=${words[$last]} symbol=${words[$last]}
module= module=
modbuildid=
fi fi
unset words[$last] unset words[$last]
...@@ -201,14 +265,6 @@ handle_line() { ...@@ -201,14 +265,6 @@ handle_line() {
echo "${words[@]}" "$symbol $module" echo "${words[@]}" "$symbol $module"
} }
if [[ $basepath == "auto" ]] ; then
module=""
symbol="kernel_init+0x0/0x0"
parse_symbol
basepath=${symbol#kernel_init (}
basepath=${basepath%/init/main.c:*)}
fi
while read line; do while read line; do
# Let's see if we have an address in the line # Let's see if we have an address in the line
if [[ $line =~ \[\<([^]]+)\>\] ]] || if [[ $line =~ \[\<([^]]+)\>\] ]] ||
...@@ -218,6 +274,9 @@ while read line; do ...@@ -218,6 +274,9 @@ while read line; do
# Is it a code line? # Is it a code line?
elif [[ $line == *Code:* ]]; then elif [[ $line == *Code:* ]]; then
decode_code "$line" decode_code "$line"
# Is it a version line?
elif [[ -n $debuginfod && $line =~ PID:\ [0-9]+\ Comm: ]]; then
debuginfod_get_vmlinux "$line"
else else
# Nothing special in this line, show it as is # Nothing special in this line, show it as is
echo "$line" echo "$line"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment