summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKonstantin Khlebnikov <khlebnikov@yandex-team.ru>2020-08-06 23:17:41 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2020-08-07 11:33:21 -0700
commit431151b64af6c8ebec85ee1db3597b56a613f526 (patch)
tree713d4ee98f3ce32c11d05eb67a7a38334ec81f18
parentecda6e27fa834b2aa37fc9ad49f89b80e9ee8f97 (diff)
downloadlinux-stable-431151b64af6c8ebec85ee1db3597b56a613f526.tar.gz
linux-stable-431151b64af6c8ebec85ee1db3597b56a613f526.tar.bz2
linux-stable-431151b64af6c8ebec85ee1db3597b56a613f526.zip
scripts/decode_stacktrace.sh: guess path to modules
Try to find module in directory with vmlinux (for fresh build). Then try standard paths where debuginfo are usually placed. Pick first file which have elf section '.debug_line'. Before: $ echo 'tap_open+0x0/0x0 [tap]' | ./scripts/decode_stacktrace.sh /usr/lib/debug/boot/vmlinux-5.4.0-37-generic WARNING! Modules path isn't set, but is needed to parse this symbol tap_open+0x0/0x0 tap After: $ echo 'tap_open+0x0/0x0 [tap]' | ./scripts/decode_stacktrace.sh /usr/lib/debug/boot/vmlinux-5.4.0-37-generic tap_open (drivers/net/tap.c:502) tap Signed-off-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Cc: Sasha Levin <sashal@kernel.org> Link: http://lkml.kernel.org/r/159282923068.248444.5461337458421616083.stgit@buzz Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rwxr-xr-xscripts/decode_stacktrace.sh36
1 files changed, 33 insertions, 3 deletions
diff --git a/scripts/decode_stacktrace.sh b/scripts/decode_stacktrace.sh
index 62a70ede7f3e..e31e253fe5bd 100755
--- a/scripts/decode_stacktrace.sh
+++ b/scripts/decode_stacktrace.sh
@@ -12,9 +12,40 @@ fi
vmlinux=$1
basepath=${2-auto}
modpath=$3
+release=""
+
declare -A cache
declare -A modcache
+find_module() {
+ if [[ "$modpath" != "" ]] ; then
+ for fn in $(find "$modpath" -name "${module//_/[-_]}.ko*") ; do
+ if readelf -WS "$fn" | grep -qwF .debug_line ; then
+ echo $fn
+ return
+ fi
+ done
+ return 1
+ fi
+
+ modpath=$(dirname "$vmlinux")
+ 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')
+ fi
+
+ for dn in {/usr/lib/debug,}/lib/modules/$release ; do
+ if [ -e "$dn" ] ; then
+ modpath="$dn"
+ find_module && return
+ fi
+ done
+
+ modpath=""
+ return 1
+}
+
parse_symbol() {
# The structure of symbol at this point is:
# ([name]+[offset]/[total length])
@@ -27,12 +58,11 @@ parse_symbol() {
elif [[ "${modcache[$module]+isset}" == "isset" ]]; then
local objfile=${modcache[$module]}
else
- if [[ $modpath == "" ]]; then
+ local objfile=$(find_module)
+ if [[ $objfile == "" ]] ; then
echo "WARNING! Modules path isn't set, but is needed to parse this symbol" >&2
return
fi
- local objfile=$(find "$modpath" -name "${module//_/[-_]}.ko*" -print -quit)
- [[ $objfile == "" ]] && return
modcache[$module]=$objfile
fi