aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/decode_stacktrace.sh
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2021-12-08 23:43:50 -0800
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2021-12-08 23:43:50 -0800
commit5d8dfaa71d87f742c53309b95cb6a8b274119027 (patch)
tree83fa5199868fb98dbe7dcb0791bc462bac77265b /scripts/decode_stacktrace.sh
parentInput: ff-core - correct magnitude setting for rumble compatibility (diff)
parentLinux 5.15 (diff)
Merge tag 'v5.15' into next
Sync up with the mainline to get the latest APIs and DT bindings.
Diffstat (limited to 'scripts/decode_stacktrace.sh')
-rwxr-xr-xscripts/decode_stacktrace.sh89
1 files changed, 74 insertions, 15 deletions
diff --git a/scripts/decode_stacktrace.sh b/scripts/decode_stacktrace.sh
index 90398347e366..5fbad61fe490 100755
--- a/scripts/decode_stacktrace.sh
+++ b/scripts/decode_stacktrace.sh
@@ -3,11 +3,10 @@
# (c) 2014, Sasha Levin <sasha.levin@oracle.com>
#set -x
-if [[ $# < 1 ]]; then
+usage() {
echo "Usage:"
- echo " $0 -r <release> | <vmlinux> [base path] [modules path]"
- exit 1
-fi
+ echo " $0 -r <release> | <vmlinux> [<base path>|auto] [<modules path>]"
+}
if [[ $1 == "-r" ]] ; then
vmlinux=""
@@ -24,6 +23,7 @@ if [[ $1 == "-r" ]] ; then
if [[ $vmlinux == "" ]] ; then
echo "ERROR! vmlinux image for release $release is not found" >&2
+ usage
exit 2
fi
else
@@ -31,12 +31,35 @@ else
basepath=${2-auto}
modpath=$3
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
declare -A cache
declare -A modcache
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
for fn in $(find "$modpath" -name "${module//_/[-_]}.ko*") ; do
if readelf -WS "$fn" | grep -qwF .debug_line ; then
@@ -51,7 +74,7 @@ find_module() {
find_module && return
if [[ $release == "" ]] ; then
- release=$(gdb -ex 'print init_uts_ns.name.release' -ex 'quit' -quiet -batch "$vmlinux" | sed -n 's/\$1 = "\(.*\)".*/\1/p')
+ release=$(gdb -ex 'print init_uts_ns.name.release' -ex 'quit' -quiet -batch "$vmlinux" 2>/dev/null | sed -n 's/\$1 = "\(.*\)".*/\1/p')
fi
for dn in {/usr/lib/debug,}/lib/modules/$release ; do
@@ -105,7 +128,7 @@ parse_symbol() {
if [[ "${cache[$module,$name]+isset}" == "isset" ]]; then
local base_addr=${cache[$module,$name]}
else
- local base_addr=$(nm "$objfile" | awk '$3 == "'$name'" && ($2 == "t" || $2 == "T") {print $1; exit}')
+ local base_addr=$(nm "$objfile" 2>/dev/null | awk '$3 == "'$name'" && ($2 == "t" || $2 == "T") {print $1; exit}')
if [[ $base_addr == "" ]] ; then
# address not found
return
@@ -129,7 +152,7 @@ parse_symbol() {
if [[ "${cache[$module,$address]+isset}" == "isset" ]]; then
local code=${cache[$module,$address]}
else
- local code=$(${CROSS_COMPILE}addr2line -i -e "$objfile" "$address")
+ local code=$(${CROSS_COMPILE}addr2line -i -e "$objfile" "$address" 2>/dev/null)
cache[$module,$address]=$code
fi
@@ -150,6 +173,27 @@ parse_symbol() {
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() {
local scripts=`dirname "${BASH_SOURCE[0]}"`
@@ -157,6 +201,14 @@ decode_code() {
}
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
# Tokenize
@@ -182,16 +234,28 @@ handle_line() {
fi
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
module=${words[$last]}
module=${module#\[}
module=${module%\]}
+ modbuildid=${module#* }
+ module=${module% *}
+ if [[ $modbuildid == $module ]]; then
+ modbuildid=
+ fi
symbol=${words[$last-1]}
unset words[$last-1]
else
# The symbol is the last element, process it
symbol=${words[$last]}
module=
+ modbuildid=
fi
unset words[$last]
@@ -201,14 +265,6 @@ handle_line() {
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
# Let's see if we have an address in the line
if [[ $line =~ \[\<([^]]+)\>\] ]] ||
@@ -218,6 +274,9 @@ while read line; do
# Is it a code line?
elif [[ $line == *Code:* ]]; then
decode_code "$line"
+ # Is it a version line?
+ elif [[ -n $debuginfod && $line =~ PID:\ [0-9]+\ Comm: ]]; then
+ debuginfod_get_vmlinux "$line"
else
# Nothing special in this line, show it as is
echo "$line"