Commit 431151b6 authored by Konstantin Khlebnikov's avatar Konstantin Khlebnikov Committed by Linus Torvalds
Browse files

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: default avatarKonstantin Khlebnikov <khlebnikov@yandex-team.ru>
Signed-off-by: default avatarAndrew 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: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent ecda6e27
Loading
Loading
Loading
Loading
+33 −3
Original line number Diff line number Diff line
@@ -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